diff options
author | 2013-03-18 16:41:57 +0000 | |
---|---|---|
committer | 2013-03-18 16:41:58 +0000 | |
commit | 952e4805f72c0835bbd158051fc56dc64d1d660d (patch) | |
tree | e0f490e56f18d26f8bb9347f90a49f55018b4539 | |
parent | 14f9fac204a04f74605c79ef38f5345425eea561 (diff) | |
parent | 13c9fdefdec907aaa339ffd67c0ded116cccba01 (diff) |
Merge "Framework changes for 464xlat." into jb-mr2-dev
3 files changed, 222 insertions, 1 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 0b3df351b63d..72d249aa283c 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -96,6 +96,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.IndentingPrintWriter; import com.android.server.am.BatteryStatsService; +import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.android.server.net.BaseNetworkObserver; @@ -154,6 +155,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mLockdownEnabled; private LockdownVpnTracker mLockdownTracker; + private Nat464Xlat mClat; + /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ private Object mRulesLock = new Object(); /** Currently active network rules by UID. */ @@ -544,9 +547,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { mVpn = new Vpn(mContext, mVpnCallback, mNetd); mVpn.startMonitoring(mContext, mTrackerHandler); + mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler); + try { mNetd.registerObserver(mTethering); mNetd.registerObserver(mDataActivityObserver); + mNetd.registerObserver(mClat); } catch (RemoteException e) { loge("Error registering observer :" + e); } @@ -2276,6 +2282,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } + // Update 464xlat state. + // TODO: Move to handleConnect() + NetworkStateTracker tracker = mNetTrackers[netType]; + if (mClat.requiresClat(netType, tracker)) { + if (mNetTrackers[netType].getNetworkInfo().isConnected()) { + mClat.startClat(tracker); + } else { + mClat.stopClat(); + } + } + // TODO: Temporary notifying upstread change to Tethering. // @see bug/4455071 /** Notify TetheringService if interface name has been changed. */ diff --git a/services/java/com/android/server/connectivity/Nat464Xlat.java b/services/java/com/android/server/connectivity/Nat464Xlat.java new file mode 100644 index 000000000000..2884eafd07f6 --- /dev/null +++ b/services/java/com/android/server/connectivity/Nat464Xlat.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2012 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 com.android.server.connectivity; + +import static android.net.ConnectivityManager.TYPE_MOBILE; + +import java.net.Inet4Address; + +import android.content.Context; +import android.net.IConnectivityManager; +import android.net.InterfaceConfiguration; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.NetworkStateTracker; +import android.net.NetworkUtils; +import android.net.RouteInfo; +import android.os.Handler; +import android.os.Message; +import android.os.INetworkManagementService; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.net.BaseNetworkObserver; + +/** + * @hide + * + * Class to manage a 464xlat CLAT daemon. + */ +public class Nat464Xlat extends BaseNetworkObserver { + private Context mContext; + private INetworkManagementService mNMService; + private IConnectivityManager mConnService; + private NetworkStateTracker mTracker; + private Handler mHandler; + + // Whether we started clatd and expect it to be running. + private boolean mIsStarted; + // Whether the clatd interface exists (i.e., clatd is running). + private boolean mIsRunning; + // The LinkProperties of the clat interface. + private LinkProperties mLP; + + // This must match the interface name in clatd.conf. + private static final String CLAT_INTERFACE_NAME = "clat4"; + + private static final String TAG = "Nat464Xlat"; + + public Nat464Xlat(Context context, INetworkManagementService nmService, + IConnectivityManager connService, Handler handler) { + mContext = context; + mNMService = nmService; + mConnService = connService; + mHandler = handler; + + mIsStarted = false; + mIsRunning = false; + mLP = new LinkProperties(); + } + + /** + * Determines whether an interface requires clat. + * @param netType the network type (one of the + * android.net.ConnectivityManager.TYPE_* constants) + * @param tracker the NetworkStateTracker corresponding to the network type. + * @return true if the interface requires clat, false otherwise. + */ + public boolean requiresClat(int netType, NetworkStateTracker tracker) { + LinkProperties lp = tracker.getLinkProperties(); + // Only support clat on mobile for now. + Slog.d(TAG, "requiresClat: netType=" + netType + ", hasIPv4Address=" + + lp.hasIPv4Address()); + return netType == TYPE_MOBILE && !lp.hasIPv4Address(); + } + + /** + * Starts the clat daemon. + * @param lp The link properties of the interface to start clatd on. + */ + public void startClat(NetworkStateTracker tracker) { + if (mIsStarted) { + Slog.e(TAG, "startClat: already started"); + return; + } + mTracker = tracker; + LinkProperties lp = mTracker.getLinkProperties(); + String iface = lp.getInterfaceName(); + Slog.i(TAG, "Starting clatd on " + iface + ", lp=" + lp); + try { + mNMService.startClatd(iface); + } catch(RemoteException e) { + Slog.e(TAG, "Error starting clat daemon: " + e); + } + mIsStarted = true; + } + + /** + * Stops the clat daemon. + */ + public void stopClat() { + if (mIsStarted) { + Slog.i(TAG, "Stopping clatd"); + try { + mNMService.stopClatd(); + } catch(RemoteException e) { + Slog.e(TAG, "Error stopping clat daemon: " + e); + } + mIsStarted = false; + mIsRunning = false; + mTracker = null; + mLP.clear(); + } else { + Slog.e(TAG, "stopClat: already stopped"); + } + } + + public boolean isStarted() { + return mIsStarted; + } + + public boolean isRunning() { + return mIsRunning; + } + + @Override + public void interfaceAdded(String iface) { + if (iface.equals(CLAT_INTERFACE_NAME)) { + Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + + " added, mIsRunning = " + mIsRunning + " -> true"); + mIsRunning = true; + + // Get the network configuration of the clat interface, store it + // in our link properties, and stack it on top of the interface + // it's running on. + try { + InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); + mLP.clear(); + mLP.setInterfaceName(iface); + RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0), null, + iface); + mLP.addRoute(ipv4Default); + mLP.addLinkAddress(config.getLinkAddress()); + mTracker.addStackedLink(mLP); + Slog.i(TAG, "Adding stacked link. tracker LP: " + + mTracker.getLinkProperties()); + } catch(RemoteException e) { + Slog.e(TAG, "Error getting link properties: " + e); + } + + // Inform ConnectivityService that things have changed. + Message msg = mHandler.obtainMessage( + NetworkStateTracker.EVENT_CONFIGURATION_CHANGED, + mTracker.getNetworkInfo()); + Slog.i(TAG, "sending message to ConnectivityService: " + msg); + msg.sendToTarget(); + } + } + + @Override + public void interfaceRemoved(String iface) { + if (iface == CLAT_INTERFACE_NAME) { + if (mIsRunning) { + NetworkUtils.resetConnections( + CLAT_INTERFACE_NAME, + NetworkUtils.RESET_IPV4_ADDRESSES); + } + Slog.i(TAG, "interface " + CLAT_INTERFACE_NAME + + " removed, mIsRunning = " + mIsRunning + " -> false"); + mIsRunning = false; + mTracker.removeStackedLink(mLP); + mLP.clear(); + Slog.i(TAG, "mLP = " + mLP); + } + } +}; diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index e4a7ead47171..32f39b7ed08b 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -35,6 +35,7 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.NetworkUtils; +import android.net.RouteInfo; import android.os.Binder; import android.os.HandlerThread; import android.os.IBinder; @@ -1345,7 +1346,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { linkProperties = mConnService.getLinkProperties(upType); } catch (RemoteException e) { } if (linkProperties != null) { - iface = linkProperties.getInterfaceName(); + // Find the interface with the default IPv4 route. It may be the + // interface described by linkProperties, or one of the interfaces + // stacked on top of it. + Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties); + RouteInfo ipv4Default = RouteInfo.selectBestRoute( + linkProperties.getAllRoutes(), Inet4Address.ANY); + if (ipv4Default != null) { + iface = ipv4Default.getInterface(); + Log.i(TAG, "Found interface " + ipv4Default.getInterface()); + } else { + Log.i(TAG, "No IPv4 upstream interface, giving up."); + } + } + + if (iface != null) { String[] dnsServers = mDefaultDnsServers; Collection<InetAddress> dnses = linkProperties.getDnses(); if (dnses != null) { |