Loading core/java/android/os/INetworkManagementService.aidl +5 −5 Original line number Original line Diff line number Diff line Loading @@ -336,19 +336,19 @@ interface INetworkManagementService void removeVpnUidRanges(int netId, in UidRange[] ranges); void removeVpnUidRanges(int netId, in UidRange[] ranges); /** /** * Start the clatd (464xlat) service * Start the clatd (464xlat) service on the given interface. */ */ void startClatd(String interfaceName); void startClatd(String interfaceName); /** /** * Stop the clatd (464xlat) service * Stop the clatd (464xlat) service on the given interface. */ */ void stopClatd(); void stopClatd(String interfaceName); /** /** * Determine whether the clatd (464xlat) service has been started * Determine whether the clatd (464xlat) service has been started on the given interface. */ */ boolean isClatdStarted(); boolean isClatdStarted(String interfaceName); /** /** * Start listening for mobile activity state changes. * Start listening for mobile activity state changes. Loading services/core/java/com/android/server/ConnectivityService.java +9 −11 Original line number Original line Diff line number Diff line Loading @@ -238,8 +238,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mLockdownEnabled; private boolean mLockdownEnabled; private LockdownVpnTracker mLockdownTracker; private LockdownVpnTracker mLockdownTracker; private Nat464Xlat mClat; /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ private Object mRulesLock = new Object(); private Object mRulesLock = new Object(); /** Currently active network rules by UID. */ /** Currently active network rules by UID. */ Loading Loading @@ -715,12 +713,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { intentFilter.addAction(Intent.ACTION_USER_STOPPING); intentFilter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiverAsUser( mContext.registerReceiverAsUser( mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler); try { try { mNetd.registerObserver(mTethering); mNetd.registerObserver(mTethering); mNetd.registerObserver(mDataActivityObserver); mNetd.registerObserver(mDataActivityObserver); mNetd.registerObserver(mClat); } catch (RemoteException e) { } catch (RemoteException e) { loge("Error registering observer :" + e); loge("Error registering observer :" + e); } } Loading Loading @@ -3549,7 +3545,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // we do anything else, make sure its LinkProperties are accurate. // we do anything else, make sure its LinkProperties are accurate. mClat.fixupLinkProperties(networkAgent, oldLp); if (networkAgent.clatd != null) { networkAgent.clatd.fixupLinkProperties(oldLp); } updateInterfaces(newLp, oldLp, netId); updateInterfaces(newLp, oldLp, netId); updateMtu(newLp, oldLp); updateMtu(newLp, oldLp); Loading @@ -3568,15 +3566,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } } } private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo na) { private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) { final boolean wasRunningClat = mClat.isRunningClat(na); final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted(); final boolean shouldRunClat = Nat464Xlat.requiresClat(na); final boolean shouldRunClat = Nat464Xlat.requiresClat(nai); if (!wasRunningClat && shouldRunClat) { if (!wasRunningClat && shouldRunClat) { // Start clatd. If it's already been started but is not running yet, this is a no-op. nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai); mClat.startClat(na); nai.clatd.start(); } else if (wasRunningClat && !shouldRunClat) { } else if (wasRunningClat && !shouldRunClat) { mClat.stopClat(); nai.clatd.stop(); } } } } Loading services/core/java/com/android/server/NetworkManagementService.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -1854,23 +1854,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } @Override @Override public void stopClatd() throws IllegalStateException { public void stopClatd(String interfaceName) throws IllegalStateException { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { try { mConnector.execute("clatd", "stop"); mConnector.execute("clatd", "stop", interfaceName); } catch (NativeDaemonConnectorException e) { } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); throw e.rethrowAsParcelableException(); } } } } @Override @Override public boolean isClatdStarted() { public boolean isClatdStarted(String interfaceName) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); final NativeDaemonEvent event; final NativeDaemonEvent event; try { try { event = mConnector.execute("clatd", "status"); event = mConnector.execute("clatd", "status", interfaceName); } catch (NativeDaemonConnectorException e) { } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); throw e.rethrowAsParcelableException(); } } Loading services/core/java/com/android/server/connectivity/Nat464Xlat.java +149 −114 Original line number Original line Diff line number Diff line Loading @@ -43,45 +43,41 @@ import com.android.server.net.BaseNetworkObserver; * Class to manage a 464xlat CLAT daemon. * Class to manage a 464xlat CLAT daemon. */ */ public class Nat464Xlat extends BaseNetworkObserver { public class Nat464Xlat extends BaseNetworkObserver { private Context mContext; private static final String TAG = "Nat464Xlat"; private INetworkManagementService mNMService; private IConnectivityManager mConnService; // This must match the interface prefix in clatd.c. // Whether we started clatd and expect it to be running. private static final String CLAT_PREFIX = "v4-"; private boolean mIsStarted; // Whether the clatd interface exists (i.e., clatd is running). private final INetworkManagementService mNMService; private boolean mIsRunning; // The LinkProperties of the clat interface. private LinkProperties mLP; // Current LinkProperties of the network. Includes mLP as a stacked link when clat is active. private LinkProperties mBaseLP; // ConnectivityService Handler for LinkProperties updates. // ConnectivityService Handler for LinkProperties updates. private Handler mHandler; private final Handler mHandler; // Marker to connote which network we're augmenting. private Messenger mNetworkMessenger; // This must match the interface name in clatd.conf. // The network we're running on. private static final String CLAT_INTERFACE_NAME = "clat4"; private final NetworkAgentInfo mNetwork; private static final String TAG = "Nat464Xlat"; // Internal state variables. // // The possible states are: // - Idle: start() not called. Everything is null. // - Starting: start() called. Interfaces are non-null. isStarted() returns true. // mIsRunning is false. // - Running: start() called, and interfaceAdded() told us that mIface is up. Clat IP address // is non-null. mIsRunning is true. // // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on // its handler thread must not modify any internal state variables; they are only updated by the // interface observers, called on the notification threads. private String mBaseIface; private String mIface; private boolean mIsRunning; public Nat464Xlat(Context context, INetworkManagementService nmService, public Nat464Xlat( IConnectivityManager connService, Handler handler) { Context context, INetworkManagementService nmService, mContext = context; Handler handler, NetworkAgentInfo nai) { mNMService = nmService; mNMService = nmService; mConnService = connService; mHandler = handler; mHandler = handler; mNetwork = nai; mIsStarted = false; mIsRunning = false; mLP = new LinkProperties(); // If this is a runtime restart, it's possible that clatd is already // running, but we don't know about it. If so, stop it. try { if (mNMService.isClatdStarted()) { mNMService.stopClatd(); } } catch(RemoteException e) {} // Well, we tried. } } /** /** Loading @@ -94,102 +90,112 @@ public class Nat464Xlat extends BaseNetworkObserver { final boolean connected = nai.networkInfo.isConnected(); final boolean connected = nai.networkInfo.isConnected(); final boolean hasIPv4Address = final boolean hasIPv4Address = (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; Slog.d(TAG, "requiresClat: netType=" + netType + ", connected=" + connected + ", hasIPv4Address=" + hasIPv4Address); // Only support clat on mobile for now. // Only support clat on mobile for now. return netType == TYPE_MOBILE && connected && !hasIPv4Address; return netType == TYPE_MOBILE && connected && !hasIPv4Address; } } public boolean isRunningClat(NetworkAgentInfo network) { /** return mNetworkMessenger == network.messenger; * Determines whether clatd is started. Always true, except a) if start has not yet been called, * or b) if our interface was removed. */ public boolean isStarted() { return mIface != null; } } /** /** * Starts the clat daemon. * Clears internal state. Must not be called by ConnectivityService. * @param lp The link properties of the interface to start clatd on. */ */ public void startClat(NetworkAgentInfo network) { private void clear() { if (mNetworkMessenger != null && mNetworkMessenger != network.messenger) { mIface = null; Slog.e(TAG, "startClat: too many networks requesting clat"); mBaseIface = null; return; mIsRunning = false; } } mNetworkMessenger = network.messenger; LinkProperties lp = network.linkProperties; /** mBaseLP = new LinkProperties(lp); * Starts the clat daemon. Called by ConnectivityService on the handler thread. if (mIsStarted) { */ public void start() { if (isStarted()) { Slog.e(TAG, "startClat: already started"); Slog.e(TAG, "startClat: already started"); return; return; } } String iface = lp.getInterfaceName(); Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp); if (mNetwork.linkProperties == null) { Slog.e(TAG, "startClat: Can't start clat with null LinkProperties"); return; } try { try { mNMService.startClatd(iface); mNMService.registerObserver(this); } catch(RemoteException e) { } catch(RemoteException e) { Slog.e(TAG, "Error starting clat daemon: " + e); Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork); return; } mBaseIface = mNetwork.linkProperties.getInterfaceName(); if (mBaseIface == null) { Slog.e(TAG, "startClat: Can't start clat on null interface"); return; } mIface = CLAT_PREFIX + mBaseIface; // From now on, isStarted() will return true. Slog.i(TAG, "Starting clatd on " + mBaseIface); try { mNMService.startClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error starting clatd: " + e); } } mIsStarted = true; } } /** /** * Stops the clat daemon. * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ */ public void stopClat() { public void stop() { if (mIsStarted) { if (isStarted()) { Slog.i(TAG, "Stopping clatd"); Slog.i(TAG, "Stopping clatd"); try { try { mNMService.stopClatd(); mNMService.stopClatd(mBaseIface); } catch(RemoteException e) { } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error stopping clat daemon: " + e); Slog.e(TAG, "Error stopping clatd: " + e); } } mIsStarted = false; // When clatd stops and its interface is deleted, interfaceRemoved() will notify mIsRunning = false; // ConnectivityService and call clear(). mNetworkMessenger = null; mBaseLP = null; mLP.clear(); } else { } else { Slog.e(TAG, "stopClat: already stopped"); Slog.e(TAG, "clatd: already stopped"); } } } } private void updateConnectivityService() { private void updateConnectivityService(LinkProperties lp) { Message msg = mHandler.obtainMessage( Message msg = mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, lp); NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP); msg.replyTo = mNetwork.messenger; msg.replyTo = mNetworkMessenger; Slog.i(TAG, "sending message to ConnectivityService: " + msg); Slog.i(TAG, "sending message to ConnectivityService: " + msg); msg.sendToTarget(); msg.sendToTarget(); } } // Copies the stacked clat link in oldLp, if any, to the LinkProperties in nai. /** public void fixupLinkProperties(NetworkAgentInfo nai, LinkProperties oldLp) { * Copies the stacked clat link in oldLp, if any, to the LinkProperties in mNetwork. if (isRunningClat(nai) && * This is necessary because the LinkProperties in mNetwork come from the transport layer, which nai.linkProperties != null && * has no idea that 464xlat is running on top of it. !nai.linkProperties.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME)) { */ Slog.d(TAG, "clatd running, updating NAI for " + nai.linkProperties.getInterfaceName()); public void fixupLinkProperties(LinkProperties oldLp) { if (mNetwork.clatd != null && mIsRunning && mNetwork.linkProperties != null && !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { Slog.d(TAG, "clatd running, updating NAI for " + mIface); for (LinkProperties stacked: oldLp.getStackedLinks()) { for (LinkProperties stacked: oldLp.getStackedLinks()) { if (CLAT_INTERFACE_NAME.equals(stacked.getInterfaceName())) { if (mIface.equals(stacked.getInterfaceName())) { nai.linkProperties.addStackedLink(stacked); mNetwork.linkProperties.addStackedLink(stacked); break; break; } } } } } } } } @Override private LinkProperties makeLinkProperties(LinkAddress clatAddress) { public void interfaceAdded(String iface) { LinkProperties stacked = new LinkProperties(); if (iface.equals(CLAT_INTERFACE_NAME)) { stacked.setInterfaceName(mIface); Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + " added, mIsRunning = " + mIsRunning + " -> true"); mIsRunning = true; // Create the LinkProperties for the clat interface by fetching the // IPv4 address for the interface and adding an IPv4 default route, // then stack the LinkProperties on top of the link it's running on. try { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); LinkAddress clatAddress = config.getLinkAddress(); mLP.clear(); mLP.setInterfaceName(iface); // Although the clat interface is a point-to-point tunnel, we don't // Although the clat interface is a point-to-point tunnel, we don't // point the route directly at the interface because some apps don't // point the route directly at the interface because some apps don't Loading @@ -197,34 +203,63 @@ public class Nat464Xlat extends BaseNetworkObserver { // http://b/9597516). Instead, set the next hop of the route to the // http://b/9597516). Instead, set the next hop of the route to the // clat IPv4 address itself (for those apps, it doesn't matter what // clat IPv4 address itself (for those apps, it doesn't matter what // the IP of the gateway is, only that there is one). // the IP of the gateway is, only that there is one). RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), RouteInfo ipv4Default = new RouteInfo( clatAddress.getAddress(), iface); new LinkAddress(Inet4Address.ANY, 0), mLP.addRoute(ipv4Default); clatAddress.getAddress(), mIface); mLP.addLinkAddress(clatAddress); stacked.addRoute(ipv4Default); mBaseLP.addStackedLink(mLP); stacked.addLinkAddress(clatAddress); Slog.i(TAG, "Adding stacked link. tracker LP: " + mBaseLP); return stacked; updateConnectivityService(); } @Override public void interfaceAdded(String iface) { // Called by the InterfaceObserver on its own thread, so can race with stop(). if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true"); LinkAddress clatAddress; try { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); clatAddress = config.getLinkAddress(); } catch(RemoteException e) { } catch(RemoteException e) { Slog.e(TAG, "Error getting link properties: " + e); Slog.e(TAG, "Error getting link properties: " + e); return; } if (!mIsRunning) { mIsRunning = true; LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.addStackedLink(makeLinkProperties(clatAddress)); Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); updateConnectivityService(lp); } } } } } } @Override @Override public void interfaceRemoved(String iface) { public void interfaceRemoved(String iface) { if (iface == CLAT_INTERFACE_NAME) { if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); if (mIsRunning) { if (mIsRunning) { NetworkUtils.resetConnections( // The interface going away likely means clatd has crashed. Ask netd to stop it, CLAT_INTERFACE_NAME, // because otherwise when we try to start it again on the same base interface netd NetworkUtils.RESET_IPV4_ADDRESSES); // will complain that it's already started. mBaseLP.removeStackedLink(CLAT_INTERFACE_NAME); // updateConnectivityService(); // Note that this method can be called by the interface observer at the same time } // that ConnectivityService calls stop(). In this case, the second call to Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + // stopClatd() will just throw IllegalStateException, which we'll ignore. " removed, mIsRunning = " + mIsRunning + " -> false"); try { mIsRunning = false; mNMService.unregisterObserver(this); mLP.clear(); mNMService.stopClatd(mBaseIface); Slog.i(TAG, "mLP = " + mLP); } catch (RemoteException|IllegalStateException e) { // Well, we tried. } LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.removeStackedLink(mIface); clear(); updateConnectivityService(lp); } } } } } } }; services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,9 @@ public class NetworkAgentInfo { public final Messenger messenger; public final Messenger messenger; public final AsyncChannel asyncChannel; public final AsyncChannel asyncChannel; // Used by ConnectivityService to keep track of 464xlat. public Nat464Xlat clatd; public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkMisc misc) { NetworkMisc misc) { Loading Loading
core/java/android/os/INetworkManagementService.aidl +5 −5 Original line number Original line Diff line number Diff line Loading @@ -336,19 +336,19 @@ interface INetworkManagementService void removeVpnUidRanges(int netId, in UidRange[] ranges); void removeVpnUidRanges(int netId, in UidRange[] ranges); /** /** * Start the clatd (464xlat) service * Start the clatd (464xlat) service on the given interface. */ */ void startClatd(String interfaceName); void startClatd(String interfaceName); /** /** * Stop the clatd (464xlat) service * Stop the clatd (464xlat) service on the given interface. */ */ void stopClatd(); void stopClatd(String interfaceName); /** /** * Determine whether the clatd (464xlat) service has been started * Determine whether the clatd (464xlat) service has been started on the given interface. */ */ boolean isClatdStarted(); boolean isClatdStarted(String interfaceName); /** /** * Start listening for mobile activity state changes. * Start listening for mobile activity state changes. Loading
services/core/java/com/android/server/ConnectivityService.java +9 −11 Original line number Original line Diff line number Diff line Loading @@ -238,8 +238,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mLockdownEnabled; private boolean mLockdownEnabled; private LockdownVpnTracker mLockdownTracker; private LockdownVpnTracker mLockdownTracker; private Nat464Xlat mClat; /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ private Object mRulesLock = new Object(); private Object mRulesLock = new Object(); /** Currently active network rules by UID. */ /** Currently active network rules by UID. */ Loading Loading @@ -715,12 +713,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { intentFilter.addAction(Intent.ACTION_USER_STOPPING); intentFilter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiverAsUser( mContext.registerReceiverAsUser( mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler); try { try { mNetd.registerObserver(mTethering); mNetd.registerObserver(mTethering); mNetd.registerObserver(mDataActivityObserver); mNetd.registerObserver(mDataActivityObserver); mNetd.registerObserver(mClat); } catch (RemoteException e) { } catch (RemoteException e) { loge("Error registering observer :" + e); loge("Error registering observer :" + e); } } Loading Loading @@ -3549,7 +3545,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // we do anything else, make sure its LinkProperties are accurate. // we do anything else, make sure its LinkProperties are accurate. mClat.fixupLinkProperties(networkAgent, oldLp); if (networkAgent.clatd != null) { networkAgent.clatd.fixupLinkProperties(oldLp); } updateInterfaces(newLp, oldLp, netId); updateInterfaces(newLp, oldLp, netId); updateMtu(newLp, oldLp); updateMtu(newLp, oldLp); Loading @@ -3568,15 +3566,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } } } private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo na) { private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) { final boolean wasRunningClat = mClat.isRunningClat(na); final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted(); final boolean shouldRunClat = Nat464Xlat.requiresClat(na); final boolean shouldRunClat = Nat464Xlat.requiresClat(nai); if (!wasRunningClat && shouldRunClat) { if (!wasRunningClat && shouldRunClat) { // Start clatd. If it's already been started but is not running yet, this is a no-op. nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai); mClat.startClat(na); nai.clatd.start(); } else if (wasRunningClat && !shouldRunClat) { } else if (wasRunningClat && !shouldRunClat) { mClat.stopClat(); nai.clatd.stop(); } } } } Loading
services/core/java/com/android/server/NetworkManagementService.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -1854,23 +1854,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } @Override @Override public void stopClatd() throws IllegalStateException { public void stopClatd(String interfaceName) throws IllegalStateException { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { try { mConnector.execute("clatd", "stop"); mConnector.execute("clatd", "stop", interfaceName); } catch (NativeDaemonConnectorException e) { } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); throw e.rethrowAsParcelableException(); } } } } @Override @Override public boolean isClatdStarted() { public boolean isClatdStarted(String interfaceName) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); final NativeDaemonEvent event; final NativeDaemonEvent event; try { try { event = mConnector.execute("clatd", "status"); event = mConnector.execute("clatd", "status", interfaceName); } catch (NativeDaemonConnectorException e) { } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); throw e.rethrowAsParcelableException(); } } Loading
services/core/java/com/android/server/connectivity/Nat464Xlat.java +149 −114 Original line number Original line Diff line number Diff line Loading @@ -43,45 +43,41 @@ import com.android.server.net.BaseNetworkObserver; * Class to manage a 464xlat CLAT daemon. * Class to manage a 464xlat CLAT daemon. */ */ public class Nat464Xlat extends BaseNetworkObserver { public class Nat464Xlat extends BaseNetworkObserver { private Context mContext; private static final String TAG = "Nat464Xlat"; private INetworkManagementService mNMService; private IConnectivityManager mConnService; // This must match the interface prefix in clatd.c. // Whether we started clatd and expect it to be running. private static final String CLAT_PREFIX = "v4-"; private boolean mIsStarted; // Whether the clatd interface exists (i.e., clatd is running). private final INetworkManagementService mNMService; private boolean mIsRunning; // The LinkProperties of the clat interface. private LinkProperties mLP; // Current LinkProperties of the network. Includes mLP as a stacked link when clat is active. private LinkProperties mBaseLP; // ConnectivityService Handler for LinkProperties updates. // ConnectivityService Handler for LinkProperties updates. private Handler mHandler; private final Handler mHandler; // Marker to connote which network we're augmenting. private Messenger mNetworkMessenger; // This must match the interface name in clatd.conf. // The network we're running on. private static final String CLAT_INTERFACE_NAME = "clat4"; private final NetworkAgentInfo mNetwork; private static final String TAG = "Nat464Xlat"; // Internal state variables. // // The possible states are: // - Idle: start() not called. Everything is null. // - Starting: start() called. Interfaces are non-null. isStarted() returns true. // mIsRunning is false. // - Running: start() called, and interfaceAdded() told us that mIface is up. Clat IP address // is non-null. mIsRunning is true. // // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on // its handler thread must not modify any internal state variables; they are only updated by the // interface observers, called on the notification threads. private String mBaseIface; private String mIface; private boolean mIsRunning; public Nat464Xlat(Context context, INetworkManagementService nmService, public Nat464Xlat( IConnectivityManager connService, Handler handler) { Context context, INetworkManagementService nmService, mContext = context; Handler handler, NetworkAgentInfo nai) { mNMService = nmService; mNMService = nmService; mConnService = connService; mHandler = handler; mHandler = handler; mNetwork = nai; mIsStarted = false; mIsRunning = false; mLP = new LinkProperties(); // If this is a runtime restart, it's possible that clatd is already // running, but we don't know about it. If so, stop it. try { if (mNMService.isClatdStarted()) { mNMService.stopClatd(); } } catch(RemoteException e) {} // Well, we tried. } } /** /** Loading @@ -94,102 +90,112 @@ public class Nat464Xlat extends BaseNetworkObserver { final boolean connected = nai.networkInfo.isConnected(); final boolean connected = nai.networkInfo.isConnected(); final boolean hasIPv4Address = final boolean hasIPv4Address = (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; Slog.d(TAG, "requiresClat: netType=" + netType + ", connected=" + connected + ", hasIPv4Address=" + hasIPv4Address); // Only support clat on mobile for now. // Only support clat on mobile for now. return netType == TYPE_MOBILE && connected && !hasIPv4Address; return netType == TYPE_MOBILE && connected && !hasIPv4Address; } } public boolean isRunningClat(NetworkAgentInfo network) { /** return mNetworkMessenger == network.messenger; * Determines whether clatd is started. Always true, except a) if start has not yet been called, * or b) if our interface was removed. */ public boolean isStarted() { return mIface != null; } } /** /** * Starts the clat daemon. * Clears internal state. Must not be called by ConnectivityService. * @param lp The link properties of the interface to start clatd on. */ */ public void startClat(NetworkAgentInfo network) { private void clear() { if (mNetworkMessenger != null && mNetworkMessenger != network.messenger) { mIface = null; Slog.e(TAG, "startClat: too many networks requesting clat"); mBaseIface = null; return; mIsRunning = false; } } mNetworkMessenger = network.messenger; LinkProperties lp = network.linkProperties; /** mBaseLP = new LinkProperties(lp); * Starts the clat daemon. Called by ConnectivityService on the handler thread. if (mIsStarted) { */ public void start() { if (isStarted()) { Slog.e(TAG, "startClat: already started"); Slog.e(TAG, "startClat: already started"); return; return; } } String iface = lp.getInterfaceName(); Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp); if (mNetwork.linkProperties == null) { Slog.e(TAG, "startClat: Can't start clat with null LinkProperties"); return; } try { try { mNMService.startClatd(iface); mNMService.registerObserver(this); } catch(RemoteException e) { } catch(RemoteException e) { Slog.e(TAG, "Error starting clat daemon: " + e); Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork); return; } mBaseIface = mNetwork.linkProperties.getInterfaceName(); if (mBaseIface == null) { Slog.e(TAG, "startClat: Can't start clat on null interface"); return; } mIface = CLAT_PREFIX + mBaseIface; // From now on, isStarted() will return true. Slog.i(TAG, "Starting clatd on " + mBaseIface); try { mNMService.startClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error starting clatd: " + e); } } mIsStarted = true; } } /** /** * Stops the clat daemon. * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ */ public void stopClat() { public void stop() { if (mIsStarted) { if (isStarted()) { Slog.i(TAG, "Stopping clatd"); Slog.i(TAG, "Stopping clatd"); try { try { mNMService.stopClatd(); mNMService.stopClatd(mBaseIface); } catch(RemoteException e) { } catch(RemoteException|IllegalStateException e) { Slog.e(TAG, "Error stopping clat daemon: " + e); Slog.e(TAG, "Error stopping clatd: " + e); } } mIsStarted = false; // When clatd stops and its interface is deleted, interfaceRemoved() will notify mIsRunning = false; // ConnectivityService and call clear(). mNetworkMessenger = null; mBaseLP = null; mLP.clear(); } else { } else { Slog.e(TAG, "stopClat: already stopped"); Slog.e(TAG, "clatd: already stopped"); } } } } private void updateConnectivityService() { private void updateConnectivityService(LinkProperties lp) { Message msg = mHandler.obtainMessage( Message msg = mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, lp); NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP); msg.replyTo = mNetwork.messenger; msg.replyTo = mNetworkMessenger; Slog.i(TAG, "sending message to ConnectivityService: " + msg); Slog.i(TAG, "sending message to ConnectivityService: " + msg); msg.sendToTarget(); msg.sendToTarget(); } } // Copies the stacked clat link in oldLp, if any, to the LinkProperties in nai. /** public void fixupLinkProperties(NetworkAgentInfo nai, LinkProperties oldLp) { * Copies the stacked clat link in oldLp, if any, to the LinkProperties in mNetwork. if (isRunningClat(nai) && * This is necessary because the LinkProperties in mNetwork come from the transport layer, which nai.linkProperties != null && * has no idea that 464xlat is running on top of it. !nai.linkProperties.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME)) { */ Slog.d(TAG, "clatd running, updating NAI for " + nai.linkProperties.getInterfaceName()); public void fixupLinkProperties(LinkProperties oldLp) { if (mNetwork.clatd != null && mIsRunning && mNetwork.linkProperties != null && !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { Slog.d(TAG, "clatd running, updating NAI for " + mIface); for (LinkProperties stacked: oldLp.getStackedLinks()) { for (LinkProperties stacked: oldLp.getStackedLinks()) { if (CLAT_INTERFACE_NAME.equals(stacked.getInterfaceName())) { if (mIface.equals(stacked.getInterfaceName())) { nai.linkProperties.addStackedLink(stacked); mNetwork.linkProperties.addStackedLink(stacked); break; break; } } } } } } } } @Override private LinkProperties makeLinkProperties(LinkAddress clatAddress) { public void interfaceAdded(String iface) { LinkProperties stacked = new LinkProperties(); if (iface.equals(CLAT_INTERFACE_NAME)) { stacked.setInterfaceName(mIface); Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + " added, mIsRunning = " + mIsRunning + " -> true"); mIsRunning = true; // Create the LinkProperties for the clat interface by fetching the // IPv4 address for the interface and adding an IPv4 default route, // then stack the LinkProperties on top of the link it's running on. try { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); LinkAddress clatAddress = config.getLinkAddress(); mLP.clear(); mLP.setInterfaceName(iface); // Although the clat interface is a point-to-point tunnel, we don't // Although the clat interface is a point-to-point tunnel, we don't // point the route directly at the interface because some apps don't // point the route directly at the interface because some apps don't Loading @@ -197,34 +203,63 @@ public class Nat464Xlat extends BaseNetworkObserver { // http://b/9597516). Instead, set the next hop of the route to the // http://b/9597516). Instead, set the next hop of the route to the // clat IPv4 address itself (for those apps, it doesn't matter what // clat IPv4 address itself (for those apps, it doesn't matter what // the IP of the gateway is, only that there is one). // the IP of the gateway is, only that there is one). RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), RouteInfo ipv4Default = new RouteInfo( clatAddress.getAddress(), iface); new LinkAddress(Inet4Address.ANY, 0), mLP.addRoute(ipv4Default); clatAddress.getAddress(), mIface); mLP.addLinkAddress(clatAddress); stacked.addRoute(ipv4Default); mBaseLP.addStackedLink(mLP); stacked.addLinkAddress(clatAddress); Slog.i(TAG, "Adding stacked link. tracker LP: " + mBaseLP); return stacked; updateConnectivityService(); } @Override public void interfaceAdded(String iface) { // Called by the InterfaceObserver on its own thread, so can race with stop(). if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true"); LinkAddress clatAddress; try { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); clatAddress = config.getLinkAddress(); } catch(RemoteException e) { } catch(RemoteException e) { Slog.e(TAG, "Error getting link properties: " + e); Slog.e(TAG, "Error getting link properties: " + e); return; } if (!mIsRunning) { mIsRunning = true; LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.addStackedLink(makeLinkProperties(clatAddress)); Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); updateConnectivityService(lp); } } } } } } @Override @Override public void interfaceRemoved(String iface) { public void interfaceRemoved(String iface) { if (iface == CLAT_INTERFACE_NAME) { if (isStarted() && mIface.equals(iface)) { Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); if (mIsRunning) { if (mIsRunning) { NetworkUtils.resetConnections( // The interface going away likely means clatd has crashed. Ask netd to stop it, CLAT_INTERFACE_NAME, // because otherwise when we try to start it again on the same base interface netd NetworkUtils.RESET_IPV4_ADDRESSES); // will complain that it's already started. mBaseLP.removeStackedLink(CLAT_INTERFACE_NAME); // updateConnectivityService(); // Note that this method can be called by the interface observer at the same time } // that ConnectivityService calls stop(). In this case, the second call to Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + // stopClatd() will just throw IllegalStateException, which we'll ignore. " removed, mIsRunning = " + mIsRunning + " -> false"); try { mIsRunning = false; mNMService.unregisterObserver(this); mLP.clear(); mNMService.stopClatd(mBaseIface); Slog.i(TAG, "mLP = " + mLP); } catch (RemoteException|IllegalStateException e) { // Well, we tried. } LinkProperties lp = new LinkProperties(mNetwork.linkProperties); lp.removeStackedLink(mIface); clear(); updateConnectivityService(lp); } } } } } } };
services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,9 @@ public class NetworkAgentInfo { public final Messenger messenger; public final Messenger messenger; public final AsyncChannel asyncChannel; public final AsyncChannel asyncChannel; // Used by ConnectivityService to keep track of 464xlat. public Nat464Xlat clatd; public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkMisc misc) { NetworkMisc misc) { Loading