diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ec83a03f8a..adf536bbf4 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2269,7 +2269,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED); mNetworkAgentInfos.remove(msg.replyTo); - updateClat(null, nai.linkProperties, nai); + maybeStopClat(nai); synchronized (mNetworkForNetId) { // Remove the NetworkAgent, but don't mark the netId as // available until we've told netd to delete it below. @@ -4382,7 +4382,8 @@ public class ConnectivityService extends IConnectivityManager.Stub updateRoutes(newLp, oldLp, netId); updateDnses(newLp, oldLp, netId); - updateClat(newLp, oldLp, networkAgent); + // Start or stop clat accordingly to network state. + updateClat(networkAgent); if (isDefaultNetwork(networkAgent)) { handleApplyDefaultProxy(newLp.getHttpProxy()); } else { @@ -4397,18 +4398,32 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent); } - private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) { - final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted(); - final boolean shouldRunClat = Nat464Xlat.requiresClat(nai); - - if (!wasRunningClat && shouldRunClat) { - nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai); - nai.clatd.start(); - } else if (wasRunningClat && !shouldRunClat) { - nai.clatd.stop(); + private void updateClat(NetworkAgentInfo nai) { + if (Nat464Xlat.requiresClat(nai)) { + maybeStartClat(nai); + } else { + maybeStopClat(nai); } } + /** Ensure clat has started for this network. */ + private void maybeStartClat(NetworkAgentInfo nai) { + if (nai.clatd != null && nai.clatd.isStarted()) { + return; + } + nai.clatd = new Nat464Xlat(mNetd, mTrackerHandler, nai); + nai.clatd.start(); + } + + /** Ensure clat has stopped for this network. */ + private void maybeStopClat(NetworkAgentInfo nai) { + if (nai.clatd == null) { + return; + } + nai.clatd.stop(); + nai.clatd = null; + } + private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) { // Marks are only available on WiFi interaces. Checking for // marks on unsupported interfaces is harmless. diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index b390884713..27426d7bde 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -18,7 +18,6 @@ package com.android.server.connectivity; import java.net.Inet4Address; -import android.content.Context; import android.net.InterfaceConfiguration; import android.net.ConnectivityManager; import android.net.LinkAddress; @@ -35,17 +34,18 @@ import com.android.server.net.BaseNetworkObserver; import com.android.internal.util.ArrayUtils; /** - * @hide - * * Class to manage a 464xlat CLAT daemon. + * + * @hide */ public class Nat464Xlat extends BaseNetworkObserver { - private static final String TAG = "Nat464Xlat"; + private static final String TAG = Nat464Xlat.class.getSimpleName(); // This must match the interface prefix in clatd.c. private static final String CLAT_PREFIX = "v4-"; - // The network types we will start clatd on. + // The network types we will start clatd on, + // allowing clat only on networks for which we can support IPv6-only. private static final int[] NETWORK_TYPES = { ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI, @@ -76,9 +76,7 @@ public class Nat464Xlat extends BaseNetworkObserver { private String mIface; private boolean mIsRunning; - public Nat464Xlat( - Context context, INetworkManagementService nmService, - Handler handler, NetworkAgentInfo nai) { + public Nat464Xlat(INetworkManagementService nmService, Handler handler, NetworkAgentInfo nai) { mNMService = nmService; mHandler = handler; mNetwork = nai; @@ -90,13 +88,14 @@ public class Nat464Xlat extends BaseNetworkObserver { * @return true if the network requires clat, false otherwise. */ public static boolean requiresClat(NetworkAgentInfo nai) { + // TODO: migrate to NetworkCapabilities.TRANSPORT_*. final int netType = nai.networkInfo.getType(); + final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); final boolean connected = nai.networkInfo.isConnected(); + // We only run clat on networks that don't have a native IPv4 address. final boolean hasIPv4Address = - (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; - // Only support clat on mobile and wifi for now, because these are the only IPv6-only - // networks we can connect to. - return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType); + (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address(); + return supported && connected && !hasIPv4Address; } /** @@ -227,6 +226,7 @@ public class Nat464Xlat extends BaseNetworkObserver { } private void maybeSetIpv6NdOffload(String iface, boolean on) { + // TODO: migrate to NetworkCapabilities.TRANSPORT_*. if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) { return; } @@ -286,4 +286,9 @@ public class Nat464Xlat extends BaseNetworkObserver { } } } + + @Override + public String toString() { + return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mIsRunning: " + mIsRunning; + } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 2a618bcc2e..872923a032 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -562,13 +562,13 @@ public class NetworkAgentInfo implements Comparable { "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " + + "clat{" + clatd + "} " + "}"; } public String name() { return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" + - networkInfo.getSubtypeName() + ") - " + - (network == null ? "null" : network.toString()) + "]"; + networkInfo.getSubtypeName() + ") - " + Objects.toString(network) + "]"; } // Enables sorting in descending order of score.