Loading core/java/android/net/IIpSecService.aidl +7 −4 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,9 @@ package android.net; import android.net.Network; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; import android.net.IpSecSpiResponse; import android.net.IpSecTransformResponse; import android.os.Bundle; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; Loading @@ -27,16 +30,16 @@ import android.os.ParcelFileDescriptor; */ */ interface IIpSecService interface IIpSecService { { Bundle reserveSecurityParameterIndex( IpSecSpiResponse reserveSecurityParameterIndex( int direction, in String remoteAddress, int requestedSpi, in IBinder binder); int direction, in String remoteAddress, int requestedSpi, in IBinder binder); void releaseSecurityParameterIndex(int resourceId); void releaseSecurityParameterIndex(int resourceId); Bundle openUdpEncapsulationSocket(int port, in IBinder binder); IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder); void closeUdpEncapsulationSocket(in ParcelFileDescriptor socket); void closeUdpEncapsulationSocket(int resourceId); Bundle createTransportModeTransform(in IpSecConfig c, in IBinder binder); IpSecTransformResponse createTransportModeTransform(in IpSecConfig c, in IBinder binder); void deleteTransportModeTransform(int transformId); void deleteTransportModeTransform(int transformId); Loading core/java/android/net/IpSecConfig.java +12 −12 Original line number Original line Diff line number Diff line Loading @@ -40,7 +40,7 @@ public final class IpSecConfig implements Parcelable { // Minimum requirements for identifying a transform // Minimum requirements for identifying a transform // SPI identifying the IPsec flow in packet processing // SPI identifying the IPsec flow in packet processing // and a remote IP address // and a remote IP address int spi; int spiResourceId; // Encryption Algorithm // Encryption Algorithm IpSecAlgorithm encryption; IpSecAlgorithm encryption; Loading @@ -54,7 +54,7 @@ public final class IpSecConfig implements Parcelable { // For tunnel mode IPv4 UDP Encapsulation // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE int encapType; int encapType; int encapLocalPort; int encapLocalPortResourceId; int encapRemotePort; int encapRemotePort; // An interval, in seconds between the NattKeepalive packets // An interval, in seconds between the NattKeepalive packets Loading @@ -69,8 +69,8 @@ public final class IpSecConfig implements Parcelable { return localAddress; return localAddress; } } public int getSpi(int direction) { public int getSpiResourceId(int direction) { return flow[direction].spi; return flow[direction].spiResourceId; } } public InetAddress getRemoteAddress() { public InetAddress getRemoteAddress() { Loading @@ -93,8 +93,8 @@ public final class IpSecConfig implements Parcelable { return encapType; return encapType; } } public int getEncapLocalPort() { public int getEncapLocalResourceId() { return encapLocalPort; return encapLocalPortResourceId; } } public int getEncapRemotePort() { public int getEncapRemotePort() { Loading @@ -119,14 +119,14 @@ public final class IpSecConfig implements Parcelable { // TODO: Use a byte array or other better method for storing IPs that can also include scope // TODO: Use a byte array or other better method for storing IPs that can also include scope out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); out.writeParcelable(network, flags); out.writeParcelable(network, flags); out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi); out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi); out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); out.writeInt(encapType); out.writeInt(encapType); out.writeInt(encapLocalPort); out.writeInt(encapLocalPortResourceId); out.writeInt(encapRemotePort); out.writeInt(encapRemotePort); } } Loading @@ -151,18 +151,18 @@ public final class IpSecConfig implements Parcelable { localAddress = readInetAddressFromParcel(in); localAddress = readInetAddressFromParcel(in); remoteAddress = readInetAddressFromParcel(in); remoteAddress = readInetAddressFromParcel(in); network = (Network) in.readParcelable(Network.class.getClassLoader()); network = (Network) in.readParcelable(Network.class.getClassLoader()); flow[IpSecTransform.DIRECTION_IN].spi = in.readInt(); flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt(); flow[IpSecTransform.DIRECTION_IN].encryption = flow[IpSecTransform.DIRECTION_IN].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_IN].authentication = flow[IpSecTransform.DIRECTION_IN].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt(); flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt(); flow[IpSecTransform.DIRECTION_OUT].encryption = flow[IpSecTransform.DIRECTION_OUT].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_OUT].authentication = flow[IpSecTransform.DIRECTION_OUT].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); encapType = in.readInt(); encapType = in.readInt(); encapLocalPort = in.readInt(); encapLocalPortResourceId = in.readInt(); encapRemotePort = in.readInt(); encapRemotePort = in.readInt(); } } Loading core/java/android/net/IpSecManager.java +99 −46 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,10 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.NonNull; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.RemoteException; import android.util.AndroidException; import android.util.AndroidException; import android.util.Log; import dalvik.system.CloseGuard; import dalvik.system.CloseGuard; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.IOException; import java.io.IOException; Loading Loading @@ -57,12 +57,6 @@ public final class IpSecManager { public static final int SPI_UNAVAILABLE = 2; public static final int SPI_UNAVAILABLE = 2; } } /** @hide */ public static final String KEY_STATUS = "status"; /** @hide */ public static final String KEY_RESOURCE_ID = "resourceId"; /** @hide */ public static final String KEY_SPI = "spi"; /** @hide */ /** @hide */ public static final int INVALID_RESOURCE_ID = 0; public static final int INVALID_RESOURCE_ID = 0; Loading Loading @@ -128,7 +122,11 @@ public final class IpSecManager { */ */ @Override @Override public void close() { public void close() { mSpi = INVALID_SECURITY_PARAMETER_INDEX; try { mService.releaseSecurityParameterIndex(mResourceId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCloseGuard.close(); mCloseGuard.close(); } } Loading @@ -147,7 +145,7 @@ public final class IpSecManager { mService = service; mService = service; mRemoteAddress = remoteAddress; mRemoteAddress = remoteAddress; try { try { Bundle result = IpSecSpiResponse result = mService.reserveSecurityParameterIndex( mService.reserveSecurityParameterIndex( direction, remoteAddress.getHostAddress(), spi, new Binder()); direction, remoteAddress.getHostAddress(), spi, new Binder()); Loading @@ -155,7 +153,7 @@ public final class IpSecManager { throw new NullPointerException("Received null response from IpSecService"); throw new NullPointerException("Received null response from IpSecService"); } } int status = result.getInt(KEY_STATUS); int status = result.status; switch (status) { switch (status) { case Status.OK: case Status.OK: break; break; Loading @@ -168,8 +166,8 @@ public final class IpSecManager { throw new RuntimeException( throw new RuntimeException( "Unknown status returned by IpSecService: " + status); "Unknown status returned by IpSecService: " + status); } } mSpi = result.getInt(KEY_SPI); mSpi = result.spi; mResourceId = result.getInt(KEY_RESOURCE_ID); mResourceId = result.resourceId; if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); Loading @@ -185,6 +183,11 @@ public final class IpSecManager { } } mCloseGuard.open("open"); mCloseGuard.open("open"); } } /** @hide */ int getResourceId() { return mResourceId; } } } /** /** Loading @@ -201,8 +204,7 @@ public final class IpSecManager { * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved */ */ public SecurityParameterIndex reserveSecurityParameterIndex( public SecurityParameterIndex reserveSecurityParameterIndex( int direction, InetAddress remoteAddress) int direction, InetAddress remoteAddress) throws ResourceUnavailableException { throws ResourceUnavailableException { try { try { return new SecurityParameterIndex( return new SecurityParameterIndex( mService, mService, Loading Loading @@ -251,7 +253,9 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(Socket socket, IpSecTransform transform) public void applyTransportModeTransform(Socket socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { applyTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -269,15 +273,8 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { } applyTransportModeTransform(pfd, transform); /* Call down to activate a transform */ private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { mService.applyTransportModeTransform(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } } Loading @@ -295,7 +292,22 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(new ParcelFileDescriptor(socket), transform); // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method // This is behaviorally the same as the other versions, but the PFD constructor does not // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { applyTransportModeTransform(pfd, transform); } } /* Call down to activate a transform */ private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { mService.applyTransportModeTransform(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** /** Loading Loading @@ -324,7 +336,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(Socket socket, IpSecTransform transform) public void removeTransportModeTransform(Socket socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { removeTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -340,7 +354,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { removeTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -355,7 +371,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(new ParcelFileDescriptor(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { removeTransportModeTransform(pfd, transform); } } } /* Call down to activate a transform */ /* Call down to activate a transform */ Loading Loading @@ -388,33 +406,48 @@ public final class IpSecManager { * FileDescriptor. Instead, disposing of this socket requires a call to close(). * FileDescriptor. Instead, disposing of this socket requires a call to close(). */ */ public static final class UdpEncapsulationSocket implements AutoCloseable { public static final class UdpEncapsulationSocket implements AutoCloseable { private final FileDescriptor mFd; private final ParcelFileDescriptor mPfd; private final IIpSecService mService; private final IIpSecService mService; private final int mResourceId; private final int mPort; private final CloseGuard mCloseGuard = CloseGuard.get(); private final CloseGuard mCloseGuard = CloseGuard.get(); private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) throws ResourceUnavailableException { throws ResourceUnavailableException, IOException { mService = service; mService = service; mCloseGuard.open("constructor"); try { // TODO: go down to the kernel and get a socket on the specified IpSecUdpEncapResponse result = mFd = new FileDescriptor(); mService.openUdpEncapsulationSocket(port, new Binder()); switch (result.status) { case Status.OK: break; case Status.RESOURCE_UNAVAILABLE: throw new ResourceUnavailableException( "No more Sockets may be allocated by this requester."); default: throw new RuntimeException( "Unknown status returned by IpSecService: " + result.status); } mResourceId = result.resourceId; mPort = result.port; mPfd = result.fileDescriptor; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException { mService = service; mCloseGuard.open("constructor"); mCloseGuard.open("constructor"); // TODO: go get a random socket on a random port mFd = new FileDescriptor(); } } /** Access the inner UDP Encapsulation Socket */ /** Access the inner UDP Encapsulation Socket */ public FileDescriptor getSocket() { public FileDescriptor getSocket() { return mFd; if (mPfd == null) { return null; } return mPfd.getFileDescriptor(); } } /** Retrieve the port number of the inner encapsulation socket */ /** Retrieve the port number of the inner encapsulation socket */ public int getPort() { public int getPort() { return 0; // TODO get the port number from the Socket; return mPort; } } @Override @Override Loading @@ -429,7 +462,18 @@ public final class IpSecManager { * @param fd a file descriptor previously returned as a UDP Encapsulation socket. * @param fd a file descriptor previously returned as a UDP Encapsulation socket. */ */ public void close() throws IOException { public void close() throws IOException { // TODO: Go close the socket try { mService.closeUdpEncapsulationSocket(mResourceId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } try { mPfd.close(); } catch (IOException e) { Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); throw e; } mCloseGuard.close(); mCloseGuard.close(); } } Loading @@ -438,9 +482,13 @@ public final class IpSecManager { if (mCloseGuard != null) { if (mCloseGuard != null) { mCloseGuard.warnIfOpen(); mCloseGuard.warnIfOpen(); } } close(); close(); } } /** @hide */ int getResourceId() { return mResourceId; } }; }; /** /** Loading @@ -467,7 +515,13 @@ public final class IpSecManager { // socket. // socket. public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) throws IOException, ResourceUnavailableException { throws IOException, ResourceUnavailableException { // Temporary code /* * Most range checking is done in the service, but this version of the constructor expects * a valid port number, and zero cannot be checked after being passed to the service. */ if (port == 0) { throw new IllegalArgumentException("Specified port must be a valid port number!"); } return new UdpEncapsulationSocket(mService, port); return new UdpEncapsulationSocket(mService, port); } } Loading @@ -491,8 +545,7 @@ public final class IpSecManager { // socket. // socket. public UdpEncapsulationSocket openUdpEncapsulationSocket() public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { throws IOException, ResourceUnavailableException { // Temporary code return new UdpEncapsulationSocket(mService, 0); return new UdpEncapsulationSocket(mService); } } /** /** Loading core/java/android/net/IpSecSpiResponse.aidl 0 → 100644 +20 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; /** @hide */ parcelable IpSecSpiResponse; core/java/android/net/IpSecSpiResponse.java 0 → 100644 +78 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import android.os.Parcel; import android.os.Parcelable; /** * This class is used to return an SPI and corresponding status from the IpSecService to an * IpSecManager.SecurityParameterIndex. * * @hide */ public final class IpSecSpiResponse implements Parcelable { private static final String TAG = "IpSecSpiResponse"; public final int resourceId; public final int status; public final int spi; // Parcelable Methods @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(status); out.writeInt(resourceId); out.writeInt(spi); } public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) { status = inStatus; resourceId = inResourceId; spi = inSpi; } public IpSecSpiResponse(int inStatus) { if (inStatus == IpSecManager.Status.OK) { throw new IllegalArgumentException("Valid status implies other args must be provided"); } status = inStatus; resourceId = IpSecManager.INVALID_RESOURCE_ID; spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; } private IpSecSpiResponse(Parcel in) { status = in.readInt(); resourceId = in.readInt(); spi = in.readInt(); } public static final Parcelable.Creator<IpSecSpiResponse> CREATOR = new Parcelable.Creator<IpSecSpiResponse>() { public IpSecSpiResponse createFromParcel(Parcel in) { return new IpSecSpiResponse(in); } public IpSecSpiResponse[] newArray(int size) { return new IpSecSpiResponse[size]; } }; } Loading
core/java/android/net/IIpSecService.aidl +7 −4 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,9 @@ package android.net; import android.net.Network; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; import android.net.IpSecSpiResponse; import android.net.IpSecTransformResponse; import android.os.Bundle; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; Loading @@ -27,16 +30,16 @@ import android.os.ParcelFileDescriptor; */ */ interface IIpSecService interface IIpSecService { { Bundle reserveSecurityParameterIndex( IpSecSpiResponse reserveSecurityParameterIndex( int direction, in String remoteAddress, int requestedSpi, in IBinder binder); int direction, in String remoteAddress, int requestedSpi, in IBinder binder); void releaseSecurityParameterIndex(int resourceId); void releaseSecurityParameterIndex(int resourceId); Bundle openUdpEncapsulationSocket(int port, in IBinder binder); IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder); void closeUdpEncapsulationSocket(in ParcelFileDescriptor socket); void closeUdpEncapsulationSocket(int resourceId); Bundle createTransportModeTransform(in IpSecConfig c, in IBinder binder); IpSecTransformResponse createTransportModeTransform(in IpSecConfig c, in IBinder binder); void deleteTransportModeTransform(int transformId); void deleteTransportModeTransform(int transformId); Loading
core/java/android/net/IpSecConfig.java +12 −12 Original line number Original line Diff line number Diff line Loading @@ -40,7 +40,7 @@ public final class IpSecConfig implements Parcelable { // Minimum requirements for identifying a transform // Minimum requirements for identifying a transform // SPI identifying the IPsec flow in packet processing // SPI identifying the IPsec flow in packet processing // and a remote IP address // and a remote IP address int spi; int spiResourceId; // Encryption Algorithm // Encryption Algorithm IpSecAlgorithm encryption; IpSecAlgorithm encryption; Loading @@ -54,7 +54,7 @@ public final class IpSecConfig implements Parcelable { // For tunnel mode IPv4 UDP Encapsulation // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE int encapType; int encapType; int encapLocalPort; int encapLocalPortResourceId; int encapRemotePort; int encapRemotePort; // An interval, in seconds between the NattKeepalive packets // An interval, in seconds between the NattKeepalive packets Loading @@ -69,8 +69,8 @@ public final class IpSecConfig implements Parcelable { return localAddress; return localAddress; } } public int getSpi(int direction) { public int getSpiResourceId(int direction) { return flow[direction].spi; return flow[direction].spiResourceId; } } public InetAddress getRemoteAddress() { public InetAddress getRemoteAddress() { Loading @@ -93,8 +93,8 @@ public final class IpSecConfig implements Parcelable { return encapType; return encapType; } } public int getEncapLocalPort() { public int getEncapLocalResourceId() { return encapLocalPort; return encapLocalPortResourceId; } } public int getEncapRemotePort() { public int getEncapRemotePort() { Loading @@ -119,14 +119,14 @@ public final class IpSecConfig implements Parcelable { // TODO: Use a byte array or other better method for storing IPs that can also include scope // TODO: Use a byte array or other better method for storing IPs that can also include scope out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); out.writeParcelable(network, flags); out.writeParcelable(network, flags); out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi); out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi); out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); out.writeInt(encapType); out.writeInt(encapType); out.writeInt(encapLocalPort); out.writeInt(encapLocalPortResourceId); out.writeInt(encapRemotePort); out.writeInt(encapRemotePort); } } Loading @@ -151,18 +151,18 @@ public final class IpSecConfig implements Parcelable { localAddress = readInetAddressFromParcel(in); localAddress = readInetAddressFromParcel(in); remoteAddress = readInetAddressFromParcel(in); remoteAddress = readInetAddressFromParcel(in); network = (Network) in.readParcelable(Network.class.getClassLoader()); network = (Network) in.readParcelable(Network.class.getClassLoader()); flow[IpSecTransform.DIRECTION_IN].spi = in.readInt(); flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt(); flow[IpSecTransform.DIRECTION_IN].encryption = flow[IpSecTransform.DIRECTION_IN].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_IN].authentication = flow[IpSecTransform.DIRECTION_IN].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt(); flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt(); flow[IpSecTransform.DIRECTION_OUT].encryption = flow[IpSecTransform.DIRECTION_OUT].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_OUT].authentication = flow[IpSecTransform.DIRECTION_OUT].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); encapType = in.readInt(); encapType = in.readInt(); encapLocalPort = in.readInt(); encapLocalPortResourceId = in.readInt(); encapRemotePort = in.readInt(); encapRemotePort = in.readInt(); } } Loading
core/java/android/net/IpSecManager.java +99 −46 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,10 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.NonNull; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.RemoteException; import android.util.AndroidException; import android.util.AndroidException; import android.util.Log; import dalvik.system.CloseGuard; import dalvik.system.CloseGuard; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.IOException; import java.io.IOException; Loading Loading @@ -57,12 +57,6 @@ public final class IpSecManager { public static final int SPI_UNAVAILABLE = 2; public static final int SPI_UNAVAILABLE = 2; } } /** @hide */ public static final String KEY_STATUS = "status"; /** @hide */ public static final String KEY_RESOURCE_ID = "resourceId"; /** @hide */ public static final String KEY_SPI = "spi"; /** @hide */ /** @hide */ public static final int INVALID_RESOURCE_ID = 0; public static final int INVALID_RESOURCE_ID = 0; Loading Loading @@ -128,7 +122,11 @@ public final class IpSecManager { */ */ @Override @Override public void close() { public void close() { mSpi = INVALID_SECURITY_PARAMETER_INDEX; try { mService.releaseSecurityParameterIndex(mResourceId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mCloseGuard.close(); mCloseGuard.close(); } } Loading @@ -147,7 +145,7 @@ public final class IpSecManager { mService = service; mService = service; mRemoteAddress = remoteAddress; mRemoteAddress = remoteAddress; try { try { Bundle result = IpSecSpiResponse result = mService.reserveSecurityParameterIndex( mService.reserveSecurityParameterIndex( direction, remoteAddress.getHostAddress(), spi, new Binder()); direction, remoteAddress.getHostAddress(), spi, new Binder()); Loading @@ -155,7 +153,7 @@ public final class IpSecManager { throw new NullPointerException("Received null response from IpSecService"); throw new NullPointerException("Received null response from IpSecService"); } } int status = result.getInt(KEY_STATUS); int status = result.status; switch (status) { switch (status) { case Status.OK: case Status.OK: break; break; Loading @@ -168,8 +166,8 @@ public final class IpSecManager { throw new RuntimeException( throw new RuntimeException( "Unknown status returned by IpSecService: " + status); "Unknown status returned by IpSecService: " + status); } } mSpi = result.getInt(KEY_SPI); mSpi = result.spi; mResourceId = result.getInt(KEY_RESOURCE_ID); mResourceId = result.resourceId; if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); Loading @@ -185,6 +183,11 @@ public final class IpSecManager { } } mCloseGuard.open("open"); mCloseGuard.open("open"); } } /** @hide */ int getResourceId() { return mResourceId; } } } /** /** Loading @@ -201,8 +204,7 @@ public final class IpSecManager { * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved */ */ public SecurityParameterIndex reserveSecurityParameterIndex( public SecurityParameterIndex reserveSecurityParameterIndex( int direction, InetAddress remoteAddress) int direction, InetAddress remoteAddress) throws ResourceUnavailableException { throws ResourceUnavailableException { try { try { return new SecurityParameterIndex( return new SecurityParameterIndex( mService, mService, Loading Loading @@ -251,7 +253,9 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(Socket socket, IpSecTransform transform) public void applyTransportModeTransform(Socket socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { applyTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -269,15 +273,8 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { } applyTransportModeTransform(pfd, transform); /* Call down to activate a transform */ private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { mService.applyTransportModeTransform(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } } Loading @@ -295,7 +292,22 @@ public final class IpSecManager { */ */ public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { throws IOException { applyTransportModeTransform(new ParcelFileDescriptor(socket), transform); // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method // This is behaviorally the same as the other versions, but the PFD constructor does not // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { applyTransportModeTransform(pfd, transform); } } /* Call down to activate a transform */ private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { mService.applyTransportModeTransform(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** /** Loading Loading @@ -324,7 +336,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(Socket socket, IpSecTransform transform) public void removeTransportModeTransform(Socket socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { removeTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -340,7 +354,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { removeTransportModeTransform(pfd, transform); } } } /** /** Loading @@ -355,7 +371,9 @@ public final class IpSecManager { */ */ public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { throws IOException { removeTransportModeTransform(new ParcelFileDescriptor(socket), transform); try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { removeTransportModeTransform(pfd, transform); } } } /* Call down to activate a transform */ /* Call down to activate a transform */ Loading Loading @@ -388,33 +406,48 @@ public final class IpSecManager { * FileDescriptor. Instead, disposing of this socket requires a call to close(). * FileDescriptor. Instead, disposing of this socket requires a call to close(). */ */ public static final class UdpEncapsulationSocket implements AutoCloseable { public static final class UdpEncapsulationSocket implements AutoCloseable { private final FileDescriptor mFd; private final ParcelFileDescriptor mPfd; private final IIpSecService mService; private final IIpSecService mService; private final int mResourceId; private final int mPort; private final CloseGuard mCloseGuard = CloseGuard.get(); private final CloseGuard mCloseGuard = CloseGuard.get(); private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) throws ResourceUnavailableException { throws ResourceUnavailableException, IOException { mService = service; mService = service; mCloseGuard.open("constructor"); try { // TODO: go down to the kernel and get a socket on the specified IpSecUdpEncapResponse result = mFd = new FileDescriptor(); mService.openUdpEncapsulationSocket(port, new Binder()); switch (result.status) { case Status.OK: break; case Status.RESOURCE_UNAVAILABLE: throw new ResourceUnavailableException( "No more Sockets may be allocated by this requester."); default: throw new RuntimeException( "Unknown status returned by IpSecService: " + result.status); } mResourceId = result.resourceId; mPort = result.port; mPfd = result.fileDescriptor; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException { mService = service; mCloseGuard.open("constructor"); mCloseGuard.open("constructor"); // TODO: go get a random socket on a random port mFd = new FileDescriptor(); } } /** Access the inner UDP Encapsulation Socket */ /** Access the inner UDP Encapsulation Socket */ public FileDescriptor getSocket() { public FileDescriptor getSocket() { return mFd; if (mPfd == null) { return null; } return mPfd.getFileDescriptor(); } } /** Retrieve the port number of the inner encapsulation socket */ /** Retrieve the port number of the inner encapsulation socket */ public int getPort() { public int getPort() { return 0; // TODO get the port number from the Socket; return mPort; } } @Override @Override Loading @@ -429,7 +462,18 @@ public final class IpSecManager { * @param fd a file descriptor previously returned as a UDP Encapsulation socket. * @param fd a file descriptor previously returned as a UDP Encapsulation socket. */ */ public void close() throws IOException { public void close() throws IOException { // TODO: Go close the socket try { mService.closeUdpEncapsulationSocket(mResourceId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } try { mPfd.close(); } catch (IOException e) { Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); throw e; } mCloseGuard.close(); mCloseGuard.close(); } } Loading @@ -438,9 +482,13 @@ public final class IpSecManager { if (mCloseGuard != null) { if (mCloseGuard != null) { mCloseGuard.warnIfOpen(); mCloseGuard.warnIfOpen(); } } close(); close(); } } /** @hide */ int getResourceId() { return mResourceId; } }; }; /** /** Loading @@ -467,7 +515,13 @@ public final class IpSecManager { // socket. // socket. public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) throws IOException, ResourceUnavailableException { throws IOException, ResourceUnavailableException { // Temporary code /* * Most range checking is done in the service, but this version of the constructor expects * a valid port number, and zero cannot be checked after being passed to the service. */ if (port == 0) { throw new IllegalArgumentException("Specified port must be a valid port number!"); } return new UdpEncapsulationSocket(mService, port); return new UdpEncapsulationSocket(mService, port); } } Loading @@ -491,8 +545,7 @@ public final class IpSecManager { // socket. // socket. public UdpEncapsulationSocket openUdpEncapsulationSocket() public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { throws IOException, ResourceUnavailableException { // Temporary code return new UdpEncapsulationSocket(mService, 0); return new UdpEncapsulationSocket(mService); } } /** /** Loading
core/java/android/net/IpSecSpiResponse.aidl 0 → 100644 +20 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; /** @hide */ parcelable IpSecSpiResponse;
core/java/android/net/IpSecSpiResponse.java 0 → 100644 +78 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import android.os.Parcel; import android.os.Parcelable; /** * This class is used to return an SPI and corresponding status from the IpSecService to an * IpSecManager.SecurityParameterIndex. * * @hide */ public final class IpSecSpiResponse implements Parcelable { private static final String TAG = "IpSecSpiResponse"; public final int resourceId; public final int status; public final int spi; // Parcelable Methods @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(status); out.writeInt(resourceId); out.writeInt(spi); } public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) { status = inStatus; resourceId = inResourceId; spi = inSpi; } public IpSecSpiResponse(int inStatus) { if (inStatus == IpSecManager.Status.OK) { throw new IllegalArgumentException("Valid status implies other args must be provided"); } status = inStatus; resourceId = IpSecManager.INVALID_RESOURCE_ID; spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; } private IpSecSpiResponse(Parcel in) { status = in.readInt(); resourceId = in.readInt(); spi = in.readInt(); } public static final Parcelable.Creator<IpSecSpiResponse> CREATOR = new Parcelable.Creator<IpSecSpiResponse>() { public IpSecSpiResponse createFromParcel(Parcel in) { return new IpSecSpiResponse(in); } public IpSecSpiResponse[] newArray(int size) { return new IpSecSpiResponse[size]; } }; }