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
2093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull;
21d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService;
22d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context;
2393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder;
24330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor;
2593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException;
26330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException;
278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log;
28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard;
29330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor;
30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException;
31330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket;
32330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress;
33330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket;
34330e1089da80cddcd68758512370d217b19f8890Nathan Harold
35330e1089da80cddcd68758512370d217b19f8890Nathan Harold/**
36330e1089da80cddcd68758512370d217b19f8890Nathan Harold * This class contains methods for managing IPsec sessions, which will perform kernel-space
37330e1089da80cddcd68758512370d217b19f8890Nathan Harold * encryption and decryption of socket or Network traffic.
38330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
39ac11ccb1f66d5dadb6c6fd1d47408e36c48c94ceNathan Harold * @hide
40330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
41d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE)
42330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager {
43330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final String TAG = "IpSecManager";
44330e1089da80cddcd68758512370d217b19f8890Nathan Harold
45330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
4693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
4793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     *
4893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * <p>No IPsec packet may contain an SPI of 0.
4993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     */
5093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
5193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
5293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
5393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public interface Status {
5493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int OK = 0;
5593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int RESOURCE_UNAVAILABLE = 1;
5693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int SPI_UNAVAILABLE = 2;
5793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
5893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
5993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
6093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final int INVALID_RESOURCE_ID = 0;
6193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
6293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /**
63330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Indicates that the combination of remote InetAddress and SPI was non-unique for a given
64330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * request. If encountered, selection of a new SPI is required before a transform may be
65330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random
66330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * or reserved using reserveSecurityParameterIndex.
67330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
68330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SpiUnavailableException extends AndroidException {
69330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final int mSpi;
70330e1089da80cddcd68758512370d217b19f8890Nathan Harold
71330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
72330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Construct an exception indicating that a transform with the given SPI is already in use
73330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * or otherwise unavailable.
74330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
75330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param msg Description indicating the colliding SPI
76330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param spi the SPI that could not be used due to a collision
77330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
78330e1089da80cddcd68758512370d217b19f8890Nathan Harold        SpiUnavailableException(String msg, int spi) {
79330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg + "(spi: " + spi + ")");
80330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mSpi = spi;
81330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
82330e1089da80cddcd68758512370d217b19f8890Nathan Harold
83330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Retrieve the SPI that caused a collision */
84330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
85330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
86330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
87330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
88330e1089da80cddcd68758512370d217b19f8890Nathan Harold
89330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
90330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Indicates that the requested system resource for IPsec, such as a socket or other system
91330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * resource is unavailable. If this exception is thrown, try releasing allocated objects of the
92330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * type requested.
93330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
94330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class ResourceUnavailableException extends AndroidException {
95330e1089da80cddcd68758512370d217b19f8890Nathan Harold
96330e1089da80cddcd68758512370d217b19f8890Nathan Harold        ResourceUnavailableException(String msg) {
97330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg);
98330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
99330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
100330e1089da80cddcd68758512370d217b19f8890Nathan Harold
1011afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    private final IIpSecService mService;
102330e1089da80cddcd68758512370d217b19f8890Nathan Harold
103330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SecurityParameterIndex implements AutoCloseable {
1041afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
105c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold        private final InetAddress mRemoteAddress;
106330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
10793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
10893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mResourceId;
109330e1089da80cddcd68758512370d217b19f8890Nathan Harold
110330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Return the underlying SPI held by this object */
111330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
112330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
113330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
114330e1089da80cddcd68758512370d217b19f8890Nathan Harold
115330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
116330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release an SPI that was previously reserved.
117330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
118c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
119c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * applied to an IpSecTransform, it will become unusable for future transforms but should
120c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * still be closed to ensure system resources are released.
121330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
122330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
123330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public void close() {
1248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
1258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.releaseSecurityParameterIndex(mResourceId);
1268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
1278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
1288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
129330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
130330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
131330e1089da80cddcd68758512370d217b19f8890Nathan Harold
132330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
133330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() {
134330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
135330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
136330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
137330e1089da80cddcd68758512370d217b19f8890Nathan Harold
138330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
139330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
140330e1089da80cddcd68758512370d217b19f8890Nathan Harold
14193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private SecurityParameterIndex(
14293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi)
14393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throws ResourceUnavailableException, SpiUnavailableException {
14493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService = service;
14593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mRemoteAddress = remoteAddress;
14693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            try {
1478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecSpiResponse result =
14893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        mService.reserveSecurityParameterIndex(
14993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                direction, remoteAddress.getHostAddress(), spi, new Binder());
15093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
15193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (result == null) {
15293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new NullPointerException("Received null response from IpSecService");
15393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
15493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
1558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                int status = result.status;
15693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                switch (status) {
15793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.OK:
15893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        break;
15993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.RESOURCE_UNAVAILABLE:
16093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new ResourceUnavailableException(
16193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "No more SPIs may be allocated by this requester.");
16293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.SPI_UNAVAILABLE:
16393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new SpiUnavailableException("Requested SPI is unavailable", spi);
16493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    default:
16593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new RuntimeException(
16693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "Unknown status returned by IpSecService: " + status);
16793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
1688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mSpi = result.spi;
1698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
17093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
17193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
17293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
17393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
17493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
17593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mResourceId == INVALID_RESOURCE_ID) {
17693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException(
17793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            "Invalid Resource ID returned by IpSecService: " + status);
17893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
17993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
18093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            } catch (RemoteException e) {
18193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw e.rethrowFromSystemServer();
18293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            }
18393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.open("open");
18493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
1858dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
1868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
1878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        int getResourceId() {
1888dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
1898dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
19093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
191330e1089da80cddcd68758512370d217b19f8890Nathan Harold
192330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
193c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * Reserve an SPI for traffic bound towards the specified remote address.
194330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
195330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
196330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * SecurityParameterIndex#close()}.
197330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
198c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
199c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
200330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return the reserved SecurityParameterIndex
201330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
202330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     for this user
203330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
204330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
205330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public SecurityParameterIndex reserveSecurityParameterIndex(
2068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            int direction, InetAddress remoteAddress) throws ResourceUnavailableException {
2076045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        try {
2086045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            return new SecurityParameterIndex(
2096045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    mService,
2106045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    direction,
2116045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    remoteAddress,
2126045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
2136045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        } catch (SpiUnavailableException unlikely) {
2146045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new ResourceUnavailableException("No SPIs available");
2156045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
2166045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    }
2176045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold
2186045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    /**
2196045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * Reserve an SPI for traffic bound towards the specified remote address.
2206045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
2216045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
2226045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * SecurityParameterIndex#close()}.
2236045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
2246045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
2256045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
2266045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
2276045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @return the reserved SecurityParameterIndex
2286045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
2296045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *     for this user
2306045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     */
2316045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    public SecurityParameterIndex reserveSecurityParameterIndex(
232c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold            int direction, InetAddress remoteAddress, int requestedSpi)
233330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws SpiUnavailableException, ResourceUnavailableException {
2346045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
2356045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
2366045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
237c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold        return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
238330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
239330e1089da80cddcd68758512370d217b19f8890Nathan Harold
240330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
241330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
242330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
243330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform. For security reasons, attempts to send traffic to any IP address other than the
244330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * address associated with that transform will throw an IOException. In addition, if the
245330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
246330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * send() or receive() until the transform is removed from the socket by calling {@link
247330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * #removeTransportModeTransform(Socket, IpSecTransform)};
248330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
249330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a stream socket
250330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
251da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold     * @hide
252330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
253330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
254330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException {
2558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
2568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            applyTransportModeTransform(pfd, transform);
2578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
258330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
259330e1089da80cddcd68758512370d217b19f8890Nathan Harold
260330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
261330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec
262330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
263330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform. For security reasons, attempts to send traffic to any IP address other than the
264330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * address associated with that transform will throw an IOException. In addition, if the
265330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
266330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * send() or receive() until the transform is removed from the socket by calling {@link
267330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * #removeTransportModeTransform(DatagramSocket, IpSecTransform)};
268330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
269330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a datagram socket
270330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
271da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold     * @hide
272330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
273330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
274330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException {
2758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
2768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            applyTransportModeTransform(pfd, transform);
27793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
27893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
279330e1089da80cddcd68758512370d217b19f8890Nathan Harold
280330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
281b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
282b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
283b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * transform. For security reasons, attempts to send traffic to any IP address other than the
284b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * address associated with that transform will throw an IOException. In addition, if the
285b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
286b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * send() or receive() until the transform is removed from the socket by calling {@link
287da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold     * #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
288b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
289b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param socket a socket file descriptor
290b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
291b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
292b64993559b049327365bb63e81e8046a892a1033Nathan Harold    public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
293b64993559b049327365bb63e81e8046a892a1033Nathan Harold            throws IOException {
2948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
2958dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // constructor takes control and closes the user's FD when we exit the method
2968dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // This is behaviorally the same as the other versions, but the PFD constructor does not
2978dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup().
2988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
2998dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            applyTransportModeTransform(pfd, transform);
3008dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
3018dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    }
3028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
3038dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    /* Call down to activate a transform */
3048dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
3058dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try {
3068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            mService.applyTransportModeTransform(pfd, transform.getResourceId());
3078dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        } catch (RemoteException e) {
3088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw e.rethrowFromSystemServer();
3098dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
310b64993559b049327365bb63e81e8046a892a1033Nathan Harold    }
311b64993559b049327365bb63e81e8046a892a1033Nathan Harold
312b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
313330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
314330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
315330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
316330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Applications should probably not use this API directly. Instead, they should use {@link
317330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * VpnService} to provide VPN capability in a more generic fashion.
318330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
319330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a {@link Network} that will be tunneled via IP Sec.
320330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
321330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
322330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
323330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
324330e1089da80cddcd68758512370d217b19f8890Nathan Harold
325330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
326330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a transform from a given stream socket. Once removed, traffic on the socket will not
327330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
328330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * communication in the clear in the event socket reuse is desired. This operation will succeed
329330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * regardless of the underlying state of a transform. If a transform is removed, communication
330330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * on all sockets to which that transform was applied will fail until this method is called.
331330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
332330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a socket that previously had a transform applied to it.
333330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform the IPsec Transform that was previously applied to the given socket
334da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold     * @hide
335330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
3360bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
3370bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
3388dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
3398dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            removeTransportModeTransform(pfd, transform);
3408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
341330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
342330e1089da80cddcd68758512370d217b19f8890Nathan Harold
343330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
344330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a transform from a given datagram socket. Once removed, traffic on the socket will not
345330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
346330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * communication in the clear in the event socket reuse is desired. This operation will succeed
347330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * regardless of the underlying state of a transform. If a transform is removed, communication
348330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * on all sockets to which that transform was applied will fail until this method is called.
349330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
350330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a socket that previously had a transform applied to it.
351330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform the IPsec Transform that was previously applied to the given socket
352da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold     * @hide
353330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
3540bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
3550bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
3568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
3578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            removeTransportModeTransform(pfd, transform);
3588dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
359330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
360330e1089da80cddcd68758512370d217b19f8890Nathan Harold
361b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
362b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * Remove a transform from a given stream socket. Once removed, traffic on the socket will not
363b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
364b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * communication in the clear in the event socket reuse is desired. This operation will succeed
365b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * regardless of the underlying state of a transform. If a transform is removed, communication
366b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * on all sockets to which that transform was applied will fail until this method is called.
367b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
368b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param socket a socket file descriptor that previously had a transform applied to it.
369b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param transform the IPsec Transform that was previously applied to the given socket
370b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
3710bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
3720bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
3738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
3748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            removeTransportModeTransform(pfd, transform);
3758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
376b64993559b049327365bb63e81e8046a892a1033Nathan Harold    }
377b64993559b049327365bb63e81e8046a892a1033Nathan Harold
378330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Call down to activate a transform */
37993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
38093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        try {
38193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService.removeTransportModeTransform(pfd, transform.getResourceId());
38293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
38393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowFromSystemServer();
38493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
38593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
386330e1089da80cddcd68758512370d217b19f8890Nathan Harold
387330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
388330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
389330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
390330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
391330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * lost, all traffic will drop.
392330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
393330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a network that currently has transform applied to it.
394330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
395330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     network
396330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
397330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
398330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
399330e1089da80cddcd68758512370d217b19f8890Nathan Harold
400330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
401330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Class providing access to a system-provided UDP Encapsulation Socket, which may be used for
402330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic.
403330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
404330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>The socket provided by this class cannot be re-bound or closed via the inner
405330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * FileDescriptor. Instead, disposing of this socket requires a call to close().
406330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
407330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class UdpEncapsulationSocket implements AutoCloseable {
4088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final ParcelFileDescriptor mPfd;
4091afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
4108dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final int mResourceId;
4118dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final int mPort;
412330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
413330e1089da80cddcd68758512370d217b19f8890Nathan Harold
41493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
4158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throws ResourceUnavailableException, IOException {
4161afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold            mService = service;
4178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
4188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecUdpEncapResponse result =
4198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        mService.openUdpEncapsulationSocket(port, new Binder());
4208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                switch (result.status) {
4218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.OK:
4228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        break;
4238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.RESOURCE_UNAVAILABLE:
4248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new ResourceUnavailableException(
4258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "No more Sockets may be allocated by this requester.");
4268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    default:
4278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new RuntimeException(
4288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "Unknown status returned by IpSecService: " + result.status);
4298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                }
4308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
4318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPort = result.port;
4328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd = result.fileDescriptor;
4338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
4348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
4358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
436330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.open("constructor");
437330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
438330e1089da80cddcd68758512370d217b19f8890Nathan Harold
439330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Access the inner UDP Encapsulation Socket */
440330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public FileDescriptor getSocket() {
4418dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            if (mPfd == null) {
4428dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                return null;
4438dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
4448dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPfd.getFileDescriptor();
445330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
446330e1089da80cddcd68758512370d217b19f8890Nathan Harold
447330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Retrieve the port number of the inner encapsulation socket */
448330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getPort() {
4498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPort;
450330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
451330e1089da80cddcd68758512370d217b19f8890Nathan Harold
452330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
453330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
454330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release the resources that have been reserved for this Socket.
455330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
456330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>This method closes the underlying socket, reducing a user's allocated sockets in the
457330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * system. This must be done as part of cleanup following use of a socket. Failure to do so
458330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * will cause the socket to count against a total allocation limit for IpSec and eventually
459330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * fail due to resource limits.
460330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
461330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
462330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
4630bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold        public void close() throws IOException {
4648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
4658dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.closeUdpEncapsulationSocket(mResourceId);
4668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
4678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
4688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
4698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
4708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
4718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd.close();
4728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (IOException e) {
4738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
4748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e;
4758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
476330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
477330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
478330e1089da80cddcd68758512370d217b19f8890Nathan Harold
479330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
480330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() throws Throwable {
481330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
482330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
483330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
484330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
485330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
4868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
4878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
4888dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        int getResourceId() {
4898dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
4908dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
491330e1089da80cddcd68758512370d217b19f8890Nathan Harold    };
492330e1089da80cddcd68758512370d217b19f8890Nathan Harold
493330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
494330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Open a socket that is bound to a free UDP port on the system.
495330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
496330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
497330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
498330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Encapsulation port.
499330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
500330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
501330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * socket port. Explicitly opening this port is only necessary if communication is desired on
502330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * that port.
503330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
504330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this
505330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     method will bind to the specified port or fail. To retrieve the port number, call {@link
506330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     android.system.Os#getsockname(FileDescriptor)}.
507330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime
508330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     of the object.
509330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
510330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
511330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
512330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
513330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
514330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
515330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
516330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
5178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /*
5188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * Most range checking is done in the service, but this version of the constructor expects
5198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * a valid port number, and zero cannot be checked after being passed to the service.
5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         */
5218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        if (port == 0) {
5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw new IllegalArgumentException("Specified port must be a valid port number!");
5238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
5241afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        return new UdpEncapsulationSocket(mService, port);
525330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
526330e1089da80cddcd68758512370d217b19f8890Nathan Harold
527330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
528330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Open a socket that is bound to a port selected by the system.
529330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
530330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
531330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
532330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Encapsulation port.
533330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
534330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
535330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * socket port. Explicitly opening this port is only necessary if communication is desired on
536330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * that port.
537330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
538330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port
539330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
540330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
541330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
542330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
543330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
544330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
545330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket()
546330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
5478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        return new UdpEncapsulationSocket(mService, 0);
548330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
549330e1089da80cddcd68758512370d217b19f8890Nathan Harold
550330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
551330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Retrieve an instance of an IpSecManager within you application context
552330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
553330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param context the application context for this manager
554330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
555330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
5561afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    public IpSecManager(IIpSecService service) {
557330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mService = checkNotNull(service, "missing service");
558330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
559330e1089da80cddcd68758512370d217b19f8890Nathan Harold}
560