Loading services/core/java/com/android/server/connectivity/Vpn.java +177 −40 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.os.PowerWhitelistManager.REASON_VPN; import static android.os.UserHandle.PER_USER_RANGE; import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; import static java.util.Objects.requireNonNull; Loading Loading @@ -84,6 +85,7 @@ import android.net.VpnManager; import android.net.VpnProfileState; import android.net.VpnService; import android.net.VpnTransportInfo; import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.ChildSessionConfiguration; import android.net.ipsec.ike.ChildSessionParams; Loading @@ -93,6 +95,7 @@ import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.exceptions.IkeIOException; import android.net.ipsec.ike.exceptions.IkeNetworkLostException; import android.net.ipsec.ike.exceptions.IkeNonProtocolException; import android.net.ipsec.ike.exceptions.IkeProtocolException; Loading Loading @@ -140,6 +143,7 @@ import com.android.net.module.util.NetworkStackConstants; import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.net.BaseNetworkObserver; import com.android.server.vcn.util.MtuUtils; import com.android.server.vcn.util.PersistableBundleUtils; import libcore.io.IoUtils; Loading @@ -152,6 +156,8 @@ import java.io.OutputStream; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; Loading @@ -165,6 +171,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; Loading Loading @@ -551,6 +558,24 @@ public class Vpn { return DATA_STALL_RESET_DELAYS_SEC[count]; } } /** Gets the MTU of an interface using Java NetworkInterface primitives */ public int getJavaNetworkInterfaceMtu(@Nullable String iface, int defaultValue) throws SocketException { if (iface == null) return defaultValue; final NetworkInterface networkInterface = NetworkInterface.getByName(iface); return networkInterface == null ? defaultValue : networkInterface.getMTU(); } /** Calculates the VPN Network's max MTU based on underlying network and configuration */ public int calculateVpnMtu( @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu, boolean isIpv4) { return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4); } } @VisibleForTesting Loading Loading @@ -1397,6 +1422,11 @@ public class Vpn { } private LinkProperties makeLinkProperties() { // The design of disabling IPv6 is only enabled for IKEv2 VPN because it needs additional // logic to handle IPv6 only VPN, and the IPv6 only VPN may be restarted when its MTU // is lower than 1280. The logic is controlled by IKEv2VpnRunner, so the design is only // enabled for IKEv2 VPN. final boolean disableIPV6 = (isIkev2VpnRunner() && mConfig.mtu < IPV6_MIN_MTU); boolean allowIPv4 = mConfig.allowIPv4; boolean allowIPv6 = mConfig.allowIPv6; Loading @@ -1406,6 +1436,7 @@ public class Vpn { if (mConfig.addresses != null) { for (LinkAddress address : mConfig.addresses) { if (disableIPV6 && address.isIpv6()) continue; lp.addLinkAddress(address); allowIPv4 |= address.getAddress() instanceof Inet4Address; allowIPv6 |= address.getAddress() instanceof Inet6Address; Loading @@ -1414,8 +1445,9 @@ public class Vpn { if (mConfig.routes != null) { for (RouteInfo route : mConfig.routes) { final InetAddress address = route.getDestination().getAddress(); if (disableIPV6 && address instanceof Inet6Address) continue; lp.addRoute(route); InetAddress address = route.getDestination().getAddress(); if (route.getType() == RouteInfo.RTN_UNICAST) { allowIPv4 |= address instanceof Inet4Address; Loading @@ -1426,7 +1458,8 @@ public class Vpn { if (mConfig.dnsServers != null) { for (String dnsServer : mConfig.dnsServers) { InetAddress address = InetAddresses.parseNumericAddress(dnsServer); final InetAddress address = InetAddresses.parseNumericAddress(dnsServer); if (disableIPV6 && address instanceof Inet6Address) continue; lp.addDnsServer(address); allowIPv4 |= address instanceof Inet4Address; allowIPv6 |= address instanceof Inet6Address; Loading @@ -1440,7 +1473,7 @@ public class Vpn { NetworkStackConstants.IPV4_ADDR_ANY, 0), null /*gateway*/, null /*iface*/, RTN_UNREACHABLE)); } if (!allowIPv6) { if (!allowIPv6 || disableIPV6) { lp.addRoute(new RouteInfo(new IpPrefix( NetworkStackConstants.IPV6_ADDR_ANY, 0), null /*gateway*/, null /*iface*/, RTN_UNREACHABLE)); Loading Loading @@ -1576,6 +1609,18 @@ public class Vpn { updateState(DetailedState.DISCONNECTED, "agentDisconnect"); } @GuardedBy("this") private void startNewNetworkAgent(NetworkAgent oldNetworkAgent, String reason) { // Initialize the state for a new agent, while keeping the old one connected // in case this new connection fails. mNetworkAgent = null; updateState(DetailedState.CONNECTING, reason); // Bringing up a new NetworkAgent to prevent the data leakage before tearing down the old // NetworkAgent. agentConnect(); agentDisconnect(oldNetworkAgent); } /** * Establish a VPN network and return the file descriptor of the VPN interface. This methods * returns {@code null} if the application is revoked or not prepared. Loading Loading @@ -1665,16 +1710,7 @@ public class Vpn { setUnderlyingNetworks(config.underlyingNetworks); } } else { // Initialize the state for a new agent, while keeping the old one connected // in case this new connection fails. mNetworkAgent = null; updateState(DetailedState.CONNECTING, "establish"); // Set up forwarding and DNS rules. agentConnect(); // Remove the old tun's user forwarding rules // The new tun's user rules have already been added above so they will take over // as rules are deleted. This prevents data leakage as the rules are moved over. agentDisconnect(oldNetworkAgent); startNewNetworkAgent(oldNetworkAgent, "establish"); } if (oldConnection != null) { Loading Loading @@ -2711,6 +2747,17 @@ public class Vpn { void onSessionLost(int token, @Nullable Exception exception); } private static boolean isIPv6Only(List<LinkAddress> linkAddresses) { boolean hasIPV6 = false; boolean hasIPV4 = false; for (final LinkAddress address : linkAddresses) { hasIPV6 |= address.isIpv6(); hasIPV4 |= address.isIpv4(); } return hasIPV6 && !hasIPV4; } /** * Internal class managing IKEv2/IPsec VPN connectivity * Loading Loading @@ -2924,15 +2971,27 @@ public class Vpn { try { final String interfaceName = mTunnelIface.getInterfaceName(); final int maxMtu = mProfile.getMaxMtu(); final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses(); final List<String> dnsAddrStrings = new ArrayList<>(); int vpnMtu; vpnMtu = calculateVpnMtu(); // If the VPN is IPv6 only and its MTU is lower than 1280, mark the network as lost // and send the VpnManager event to the VPN app. if (isIPv6Only(internalAddresses) && vpnMtu < IPV6_MIN_MTU) { onSessionLost( token, new IkeIOException( new IOException("No valid addresses for MTU < 1280"))); return; } final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors( childConfig.getOutboundTrafficSelectors()); for (final LinkAddress address : internalAddresses) { mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength()); } for (InetAddress addr : childConfig.getInternalDnsServers()) { dnsAddrStrings.add(addr.getHostAddress()); } Loading @@ -2950,7 +3009,7 @@ public class Vpn { if (mVpnRunner != this) return; mInterface = interfaceName; mConfig.mtu = maxMtu; mConfig.mtu = vpnMtu; mConfig.interfaze = mInterface; mConfig.addresses.clear(); Loading Loading @@ -3053,12 +3112,54 @@ public class Vpn { // Ignore stale runner. if (mVpnRunner != this) return; final LinkProperties oldLp = makeLinkProperties(); final boolean underlyingNetworkHasChanged = !Arrays.equals(mConfig.underlyingNetworks, new Network[]{network}); mConfig.underlyingNetworks = new Network[] {network}; mConfig.mtu = calculateVpnMtu(); final LinkProperties newLp = makeLinkProperties(); // If MTU is < 1280, IPv6 addresses will be removed. If there are no addresses // left (e.g. IPv6-only VPN network), mark VPN as having lost the session. if (newLp.getLinkAddresses().isEmpty()) { onSessionLost( token, new IkeIOException( new IOException("No valid addresses for MTU < 1280"))); return; } final Set<LinkAddress> removedAddrs = new HashSet<>(oldLp.getLinkAddresses()); removedAddrs.removeAll(newLp.getLinkAddresses()); // If addresses were removed despite no IKE config change, IPv6 addresses must // have been removed due to MTU size. Restart the VPN to ensure all IPv6 // unconnected sockets on the new VPN network are closed and retried on the new // VPN network. if (!removedAddrs.isEmpty()) { startNewNetworkAgent( mNetworkAgent, "MTU too low for IPv6; restarting network agent"); for (LinkAddress removed : removedAddrs) { mTunnelIface.removeAddress( removed.getAddress(), removed.getPrefixLength()); } } else { // Put below 3 updates into else block is because agentConnect() will do // those things, so there is no need to do the redundant work. if (!newLp.equals(oldLp)) doSendLinkProperties(mNetworkAgent, newLp); if (underlyingNetworkHasChanged) { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) .setUnderlyingNetworks(Collections.singletonList(network)) .setUnderlyingNetworks( Collections.singletonList(network)) .build(); doSetUnderlyingNetworks(mNetworkAgent, Collections.singletonList(network)); doSetUnderlyingNetworks(mNetworkAgent, Collections.singletonList(network)); } } } mTunnelIface.setUnderlyingNetwork(network); Loading Loading @@ -3108,6 +3209,60 @@ public class Vpn { startOrMigrateIkeSession(network); } @NonNull private IkeSessionParams getIkeSessionParams(@NonNull Network underlyingNetwork) { final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); if (ikeTunConnParams != null) { final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams()) .setNetwork(underlyingNetwork); return builder.build(); } else { return VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, underlyingNetwork); } } @NonNull private ChildSessionParams getChildSessionParams() { final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); if (ikeTunConnParams != null) { return ikeTunConnParams.getTunnelModeChildSessionParams(); } else { return VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms()); } } private int calculateVpnMtu() { final Network underlyingNetwork = mIkeConnectionInfo.getNetwork(); final LinkProperties lp = mConnectivityManager.getLinkProperties(underlyingNetwork); if (underlyingNetwork == null || lp == null) { // Return the max MTU defined in VpnProfile as the fallback option when there is no // underlying network or LinkProperties is null. return mProfile.getMaxMtu(); } int underlyingMtu = lp.getMtu(); // Try to get MTU from kernel if MTU is not set in LinkProperties. if (underlyingMtu == 0) { try { underlyingMtu = mDeps.getJavaNetworkInterfaceMtu(lp.getInterfaceName(), mProfile.getMaxMtu()); } catch (SocketException e) { Log.d(TAG, "Got a SocketException when getting MTU from kernel: " + e); return mProfile.getMaxMtu(); } } return mDeps.calculateVpnMtu( getChildSessionParams().getSaProposals(), mProfile.getMaxMtu(), underlyingMtu, mIkeConnectionInfo.getLocalAddress() instanceof Inet4Address); } /** * Start a new IKE session. * Loading Loading @@ -3158,24 +3313,6 @@ public class Vpn { // (non-default) network, and start the new one. resetIkeState(); // Get Ike options from IkeTunnelConnectionParams if it's available in the // profile. final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); final IkeSessionParams ikeSessionParams; final ChildSessionParams childSessionParams; if (ikeTunConnParams != null) { final IkeSessionParams.Builder builder = new IkeSessionParams.Builder( ikeTunConnParams.getIkeSessionParams()).setNetwork(underlyingNetwork); ikeSessionParams = builder.build(); childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams(); } else { ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams( mContext, mProfile, underlyingNetwork); childSessionParams = VpnIkev2Utils.buildChildSessionParams( mProfile.getAllowedAlgorithms()); } // TODO: Remove the need for adding two unused addresses with // IPsec tunnels. final InetAddress address = InetAddress.getLocalHost(); Loading @@ -3193,8 +3330,8 @@ public class Vpn { mSession = mIkev2SessionCreator.createIkeSession( mContext, ikeSessionParams, childSessionParams, getIkeSessionParams(underlyingNetwork), getChildSessionParams(), mExecutor, new VpnIkev2Utils.IkeSessionCallbackImpl( TAG, IkeV2VpnRunner.this, token), Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +177 −40 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.os.PowerWhitelistManager.REASON_VPN; import static android.os.UserHandle.PER_USER_RANGE; import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; import static java.util.Objects.requireNonNull; Loading Loading @@ -84,6 +85,7 @@ import android.net.VpnManager; import android.net.VpnProfileState; import android.net.VpnService; import android.net.VpnTransportInfo; import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.ChildSessionConfiguration; import android.net.ipsec.ike.ChildSessionParams; Loading @@ -93,6 +95,7 @@ import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.exceptions.IkeIOException; import android.net.ipsec.ike.exceptions.IkeNetworkLostException; import android.net.ipsec.ike.exceptions.IkeNonProtocolException; import android.net.ipsec.ike.exceptions.IkeProtocolException; Loading Loading @@ -140,6 +143,7 @@ import com.android.net.module.util.NetworkStackConstants; import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.net.BaseNetworkObserver; import com.android.server.vcn.util.MtuUtils; import com.android.server.vcn.util.PersistableBundleUtils; import libcore.io.IoUtils; Loading @@ -152,6 +156,8 @@ import java.io.OutputStream; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; Loading @@ -165,6 +171,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; Loading Loading @@ -551,6 +558,24 @@ public class Vpn { return DATA_STALL_RESET_DELAYS_SEC[count]; } } /** Gets the MTU of an interface using Java NetworkInterface primitives */ public int getJavaNetworkInterfaceMtu(@Nullable String iface, int defaultValue) throws SocketException { if (iface == null) return defaultValue; final NetworkInterface networkInterface = NetworkInterface.getByName(iface); return networkInterface == null ? defaultValue : networkInterface.getMTU(); } /** Calculates the VPN Network's max MTU based on underlying network and configuration */ public int calculateVpnMtu( @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu, boolean isIpv4) { return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4); } } @VisibleForTesting Loading Loading @@ -1397,6 +1422,11 @@ public class Vpn { } private LinkProperties makeLinkProperties() { // The design of disabling IPv6 is only enabled for IKEv2 VPN because it needs additional // logic to handle IPv6 only VPN, and the IPv6 only VPN may be restarted when its MTU // is lower than 1280. The logic is controlled by IKEv2VpnRunner, so the design is only // enabled for IKEv2 VPN. final boolean disableIPV6 = (isIkev2VpnRunner() && mConfig.mtu < IPV6_MIN_MTU); boolean allowIPv4 = mConfig.allowIPv4; boolean allowIPv6 = mConfig.allowIPv6; Loading @@ -1406,6 +1436,7 @@ public class Vpn { if (mConfig.addresses != null) { for (LinkAddress address : mConfig.addresses) { if (disableIPV6 && address.isIpv6()) continue; lp.addLinkAddress(address); allowIPv4 |= address.getAddress() instanceof Inet4Address; allowIPv6 |= address.getAddress() instanceof Inet6Address; Loading @@ -1414,8 +1445,9 @@ public class Vpn { if (mConfig.routes != null) { for (RouteInfo route : mConfig.routes) { final InetAddress address = route.getDestination().getAddress(); if (disableIPV6 && address instanceof Inet6Address) continue; lp.addRoute(route); InetAddress address = route.getDestination().getAddress(); if (route.getType() == RouteInfo.RTN_UNICAST) { allowIPv4 |= address instanceof Inet4Address; Loading @@ -1426,7 +1458,8 @@ public class Vpn { if (mConfig.dnsServers != null) { for (String dnsServer : mConfig.dnsServers) { InetAddress address = InetAddresses.parseNumericAddress(dnsServer); final InetAddress address = InetAddresses.parseNumericAddress(dnsServer); if (disableIPV6 && address instanceof Inet6Address) continue; lp.addDnsServer(address); allowIPv4 |= address instanceof Inet4Address; allowIPv6 |= address instanceof Inet6Address; Loading @@ -1440,7 +1473,7 @@ public class Vpn { NetworkStackConstants.IPV4_ADDR_ANY, 0), null /*gateway*/, null /*iface*/, RTN_UNREACHABLE)); } if (!allowIPv6) { if (!allowIPv6 || disableIPV6) { lp.addRoute(new RouteInfo(new IpPrefix( NetworkStackConstants.IPV6_ADDR_ANY, 0), null /*gateway*/, null /*iface*/, RTN_UNREACHABLE)); Loading Loading @@ -1576,6 +1609,18 @@ public class Vpn { updateState(DetailedState.DISCONNECTED, "agentDisconnect"); } @GuardedBy("this") private void startNewNetworkAgent(NetworkAgent oldNetworkAgent, String reason) { // Initialize the state for a new agent, while keeping the old one connected // in case this new connection fails. mNetworkAgent = null; updateState(DetailedState.CONNECTING, reason); // Bringing up a new NetworkAgent to prevent the data leakage before tearing down the old // NetworkAgent. agentConnect(); agentDisconnect(oldNetworkAgent); } /** * Establish a VPN network and return the file descriptor of the VPN interface. This methods * returns {@code null} if the application is revoked or not prepared. Loading Loading @@ -1665,16 +1710,7 @@ public class Vpn { setUnderlyingNetworks(config.underlyingNetworks); } } else { // Initialize the state for a new agent, while keeping the old one connected // in case this new connection fails. mNetworkAgent = null; updateState(DetailedState.CONNECTING, "establish"); // Set up forwarding and DNS rules. agentConnect(); // Remove the old tun's user forwarding rules // The new tun's user rules have already been added above so they will take over // as rules are deleted. This prevents data leakage as the rules are moved over. agentDisconnect(oldNetworkAgent); startNewNetworkAgent(oldNetworkAgent, "establish"); } if (oldConnection != null) { Loading Loading @@ -2711,6 +2747,17 @@ public class Vpn { void onSessionLost(int token, @Nullable Exception exception); } private static boolean isIPv6Only(List<LinkAddress> linkAddresses) { boolean hasIPV6 = false; boolean hasIPV4 = false; for (final LinkAddress address : linkAddresses) { hasIPV6 |= address.isIpv6(); hasIPV4 |= address.isIpv4(); } return hasIPV6 && !hasIPV4; } /** * Internal class managing IKEv2/IPsec VPN connectivity * Loading Loading @@ -2924,15 +2971,27 @@ public class Vpn { try { final String interfaceName = mTunnelIface.getInterfaceName(); final int maxMtu = mProfile.getMaxMtu(); final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses(); final List<String> dnsAddrStrings = new ArrayList<>(); int vpnMtu; vpnMtu = calculateVpnMtu(); // If the VPN is IPv6 only and its MTU is lower than 1280, mark the network as lost // and send the VpnManager event to the VPN app. if (isIPv6Only(internalAddresses) && vpnMtu < IPV6_MIN_MTU) { onSessionLost( token, new IkeIOException( new IOException("No valid addresses for MTU < 1280"))); return; } final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors( childConfig.getOutboundTrafficSelectors()); for (final LinkAddress address : internalAddresses) { mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength()); } for (InetAddress addr : childConfig.getInternalDnsServers()) { dnsAddrStrings.add(addr.getHostAddress()); } Loading @@ -2950,7 +3009,7 @@ public class Vpn { if (mVpnRunner != this) return; mInterface = interfaceName; mConfig.mtu = maxMtu; mConfig.mtu = vpnMtu; mConfig.interfaze = mInterface; mConfig.addresses.clear(); Loading Loading @@ -3053,12 +3112,54 @@ public class Vpn { // Ignore stale runner. if (mVpnRunner != this) return; final LinkProperties oldLp = makeLinkProperties(); final boolean underlyingNetworkHasChanged = !Arrays.equals(mConfig.underlyingNetworks, new Network[]{network}); mConfig.underlyingNetworks = new Network[] {network}; mConfig.mtu = calculateVpnMtu(); final LinkProperties newLp = makeLinkProperties(); // If MTU is < 1280, IPv6 addresses will be removed. If there are no addresses // left (e.g. IPv6-only VPN network), mark VPN as having lost the session. if (newLp.getLinkAddresses().isEmpty()) { onSessionLost( token, new IkeIOException( new IOException("No valid addresses for MTU < 1280"))); return; } final Set<LinkAddress> removedAddrs = new HashSet<>(oldLp.getLinkAddresses()); removedAddrs.removeAll(newLp.getLinkAddresses()); // If addresses were removed despite no IKE config change, IPv6 addresses must // have been removed due to MTU size. Restart the VPN to ensure all IPv6 // unconnected sockets on the new VPN network are closed and retried on the new // VPN network. if (!removedAddrs.isEmpty()) { startNewNetworkAgent( mNetworkAgent, "MTU too low for IPv6; restarting network agent"); for (LinkAddress removed : removedAddrs) { mTunnelIface.removeAddress( removed.getAddress(), removed.getPrefixLength()); } } else { // Put below 3 updates into else block is because agentConnect() will do // those things, so there is no need to do the redundant work. if (!newLp.equals(oldLp)) doSendLinkProperties(mNetworkAgent, newLp); if (underlyingNetworkHasChanged) { mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) .setUnderlyingNetworks(Collections.singletonList(network)) .setUnderlyingNetworks( Collections.singletonList(network)) .build(); doSetUnderlyingNetworks(mNetworkAgent, Collections.singletonList(network)); doSetUnderlyingNetworks(mNetworkAgent, Collections.singletonList(network)); } } } mTunnelIface.setUnderlyingNetwork(network); Loading Loading @@ -3108,6 +3209,60 @@ public class Vpn { startOrMigrateIkeSession(network); } @NonNull private IkeSessionParams getIkeSessionParams(@NonNull Network underlyingNetwork) { final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); if (ikeTunConnParams != null) { final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams()) .setNetwork(underlyingNetwork); return builder.build(); } else { return VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, underlyingNetwork); } } @NonNull private ChildSessionParams getChildSessionParams() { final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); if (ikeTunConnParams != null) { return ikeTunConnParams.getTunnelModeChildSessionParams(); } else { return VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms()); } } private int calculateVpnMtu() { final Network underlyingNetwork = mIkeConnectionInfo.getNetwork(); final LinkProperties lp = mConnectivityManager.getLinkProperties(underlyingNetwork); if (underlyingNetwork == null || lp == null) { // Return the max MTU defined in VpnProfile as the fallback option when there is no // underlying network or LinkProperties is null. return mProfile.getMaxMtu(); } int underlyingMtu = lp.getMtu(); // Try to get MTU from kernel if MTU is not set in LinkProperties. if (underlyingMtu == 0) { try { underlyingMtu = mDeps.getJavaNetworkInterfaceMtu(lp.getInterfaceName(), mProfile.getMaxMtu()); } catch (SocketException e) { Log.d(TAG, "Got a SocketException when getting MTU from kernel: " + e); return mProfile.getMaxMtu(); } } return mDeps.calculateVpnMtu( getChildSessionParams().getSaProposals(), mProfile.getMaxMtu(), underlyingMtu, mIkeConnectionInfo.getLocalAddress() instanceof Inet4Address); } /** * Start a new IKE session. * Loading Loading @@ -3158,24 +3313,6 @@ public class Vpn { // (non-default) network, and start the new one. resetIkeState(); // Get Ike options from IkeTunnelConnectionParams if it's available in the // profile. final IkeTunnelConnectionParams ikeTunConnParams = mProfile.getIkeTunnelConnectionParams(); final IkeSessionParams ikeSessionParams; final ChildSessionParams childSessionParams; if (ikeTunConnParams != null) { final IkeSessionParams.Builder builder = new IkeSessionParams.Builder( ikeTunConnParams.getIkeSessionParams()).setNetwork(underlyingNetwork); ikeSessionParams = builder.build(); childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams(); } else { ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams( mContext, mProfile, underlyingNetwork); childSessionParams = VpnIkev2Utils.buildChildSessionParams( mProfile.getAllowedAlgorithms()); } // TODO: Remove the need for adding two unused addresses with // IPsec tunnels. final InetAddress address = InetAddress.getLocalHost(); Loading @@ -3193,8 +3330,8 @@ public class Vpn { mSession = mIkev2SessionCreator.createIkeSession( mContext, ikeSessionParams, childSessionParams, getIkeSessionParams(underlyingNetwork), getChildSessionParams(), mExecutor, new VpnIkev2Utils.IkeSessionCallbackImpl( TAG, IkeV2VpnRunner.this, token), Loading