diff options
author | Robert Greenwalt <rgreenwalt@google.com> | 2011-11-05 19:33:46 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-11-05 19:33:46 +0000 |
commit | 08d153fb8e3c92716405d9303cc700095308a8af (patch) | |
tree | 63898696bdf1c8a95ab2067dea4bbeead025f1f6 | |
parent | aaa0336f883b2f94af5e7d4a320cb9a351a2db93 (diff) | |
parent | fd900f05fb67046b97701f20626f7fd408fd8990 (diff) | |
download | frameworks_base-08d153fb8e3c92716405d9303cc700095308a8af.zip frameworks_base-08d153fb8e3c92716405d9303cc700095308a8af.tar.gz frameworks_base-08d153fb8e3c92716405d9303cc700095308a8af.tar.bz2 |
am fd900f05: am 348297ab: Merge "Start using IP tool for advanced routing." into ics-mr0
* commit 'fd900f05fb67046b97701f20626f7fd408fd8990':
Start using IP tool for advanced routing.
4 files changed, 120 insertions, 52 deletions
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index be87946..6ecc640 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -105,6 +105,18 @@ interface INetworkManagementService void removeRoute(String iface, in RouteInfo route); /** + * Add the specified route to a secondary interface + * This will go into a special route table to be accessed + * via ip rules + */ + void addSecondaryRoute(String iface, in RouteInfo route); + + /** + * Remove the specified secondary route. + */ + void removeSecondaryRoute(String iface, in RouteInfo route); + + /** * Shuts down the service */ void shutdown(); diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 851cb33..8c42f31 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -171,6 +171,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int ENABLED = 1; private static final int DISABLED = 0; + private static final boolean ADD = true; + private static final boolean REMOVE = false; + + private static final boolean TO_DEFAULT_TABLE = true; + private static final boolean TO_SECONDARY_TABLE = false; + // Share the event space with NetworkStateTracker (which can't see this // internal class but sends us events). If you change these, change // NetworkStateTracker.java too. @@ -501,7 +507,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b); - mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper()); + mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper()); mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 || mTethering.getTetherableWifiRegexs().length != 0 || mTethering.getTetherableBluetoothRegexs().length != 0) && @@ -1146,23 +1152,24 @@ public class ConnectivityService extends IConnectivityManager.Stub { return false; } - private boolean addRoute(LinkProperties p, RouteInfo r) { - return modifyRoute(p.getInterfaceName(), p, r, 0, true); + private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { + return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable); } - private boolean removeRoute(LinkProperties p, RouteInfo r) { - return modifyRoute(p.getInterfaceName(), p, r, 0, false); + private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { + return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable); } private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { - return modifyRouteToAddress(lp, addr, true); + return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE); } private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { - return modifyRouteToAddress(lp, addr, false); + return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE); } - private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) { + private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, + boolean toDefaultTable) { RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr); if (bestRoute == null) { bestRoute = RouteInfo.makeHostRoute(addr); @@ -1176,15 +1183,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway()); } } - return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd); + return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable); } private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount, - boolean doAdd) { + boolean doAdd, boolean toDefaultTable) { if ((ifaceName == null) || (lp == null) || (r == null)) return false; if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) { - loge("Error adding route - too much recursion"); + loge("Error modifying route - too much recursion"); return false; } @@ -1199,14 +1206,18 @@ public class ConnectivityService extends IConnectivityManager.Stub { // route to it's gateway bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway()); } - modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd); + modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable); } } if (doAdd) { if (VDBG) log("Adding " + r + " for interface " + ifaceName); - mAddedRoutes.add(r); try { - mNetd.addRoute(ifaceName, r); + if (toDefaultTable) { + mAddedRoutes.add(r); // only track default table - only one apps can effect + mNetd.addRoute(ifaceName, r); + } else { + mNetd.addSecondaryRoute(ifaceName, r); + } } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to add a route: " + e); @@ -1215,18 +1226,29 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { // if we remove this one and there are no more like it, then refcount==0 and // we can remove it from the table - mAddedRoutes.remove(r); - if (mAddedRoutes.contains(r) == false) { + if (toDefaultTable) { + mAddedRoutes.remove(r); + if (mAddedRoutes.contains(r) == false) { + if (VDBG) log("Removing " + r + " for interface " + ifaceName); + try { + mNetd.removeRoute(ifaceName, r); + } catch (Exception e) { + // never crash - catch them all + if (VDBG) loge("Exception trying to remove a route: " + e); + return false; + } + } else { + if (VDBG) log("not removing " + r + " as it's still in use"); + } + } else { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { - mNetd.removeRoute(ifaceName, r); + mNetd.removeSecondaryRoute(ifaceName, r); } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to remove a route: " + e); return false; } - } else { - if (VDBG) log("not removing " + r + " as it's still in use"); } } return true; @@ -1862,14 +1884,21 @@ public class ConnectivityService extends IConnectivityManager.Stub { for (RouteInfo r : routeDiff.removed) { if (isLinkDefault || ! r.isDefaultRoute()) { - removeRoute(curLp, r); + removeRoute(curLp, r, TO_DEFAULT_TABLE); + } + if (isLinkDefault == false) { + // remove from a secondary route table + removeRoute(curLp, r, TO_SECONDARY_TABLE); } } for (RouteInfo r : routeDiff.added) { if (isLinkDefault || ! r.isDefaultRoute()) { - addRoute(newLp, r); + addRoute(newLp, r, TO_DEFAULT_TABLE); } else { + // add to a secondary route table + addRoute(newLp, r, TO_SECONDARY_TABLE); + // many radios add a default route even when we don't want one. // remove the default route unless somebody else has asked for it String ifaceName = newLp.getInterfaceName(); @@ -2450,12 +2479,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); - // Short term disabling of Tethering if DUN is required. - // TODO - fix multi-connection tethering using policy-base routing - int[] upstreamConnTypes = mTethering.getUpstreamIfaceTypes(); - for (int i : upstreamConnTypes) { - if (i == ConnectivityManager.TYPE_MOBILE_DUN) return false; - } return tetherEnabledInSettings && mTetheringConfigValid; } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 4e4fe4a..6887de3 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -59,7 +59,11 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -77,6 +81,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub private static final int ADD = 1; private static final int REMOVE = 2; + private static final String DEFAULT = "default"; + private static final String SECONDARY = "secondary"; + /** * Name representing {@link #setGlobalAlert(long)} limit when delivered to * {@link INetworkManagementEventObserver#limitReached(String, String)}. @@ -505,15 +512,25 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void addRoute(String interfaceName, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); - modifyRoute(interfaceName, ADD, route); + modifyRoute(interfaceName, ADD, route, DEFAULT); } public void removeRoute(String interfaceName, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); - modifyRoute(interfaceName, REMOVE, route); + modifyRoute(interfaceName, REMOVE, route, DEFAULT); + } + + public void addSecondaryRoute(String interfaceName, RouteInfo route) { + mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); + modifyRoute(interfaceName, ADD, route, SECONDARY); } - private void modifyRoute(String interfaceName, int action, RouteInfo route) { + public void removeSecondaryRoute(String interfaceName, RouteInfo route) { + mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); + modifyRoute(interfaceName, REMOVE, route, SECONDARY); + } + + private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) { ArrayList<String> rsp; StringBuilder cmd; @@ -521,12 +538,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub switch (action) { case ADD: { - cmd = new StringBuilder("interface route add " + interfaceName); + cmd = new StringBuilder("interface route add " + interfaceName + " " + type); break; } case REMOVE: { - cmd = new StringBuilder("interface route remove " + interfaceName); + cmd = new StringBuilder("interface route remove " + interfaceName + " " + type); break; } default: @@ -833,14 +850,33 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private void modifyNat(String cmd, String internalInterface, String externalInterface) + throws SocketException { + cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface); + + NetworkInterface internalNetworkInterface = + NetworkInterface.getByName(internalInterface); + Collection<InterfaceAddress>interfaceAddresses = + internalNetworkInterface.getInterfaceAddresses(); + cmd += " " + interfaceAddresses.size(); + for (InterfaceAddress ia : interfaceAddresses) { + InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(), + ia.getNetworkPrefixLength()); + cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength(); + } + + mConnector.doCommand(cmd); + } + public void enableNat(String internalInterface, String externalInterface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")"); try { - mConnector.doCommand( - String.format("nat enable %s %s", internalInterface, externalInterface)); - } catch (NativeDaemonConnectorException e) { + modifyNat("enable", internalInterface, externalInterface); + } catch (Exception e) { + Log.e(TAG, "enableNat got Exception " + e.toString()); throw new IllegalStateException( "Unable to communicate to native daemon for enabling NAT interface"); } @@ -850,10 +886,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")"); try { - mConnector.doCommand( - String.format("nat disable %s %s", internalInterface, externalInterface)); - } catch (NativeDaemonConnectorException e) { + modifyNat("disable", internalInterface, externalInterface); + } catch (Exception e) { + Log.e(TAG, "disableNat got Exception " + e.toString()); throw new IllegalStateException( "Unable to communicate to native daemon for disabling NAT interface"); } diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 7bd29d9..e49acaf 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -91,6 +91,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private final INetworkManagementService mNMService; private final INetworkStatsService mStatsService; + private final IConnectivityManager mConnService; private Looper mLooper; private HandlerThread mThread; @@ -127,10 +128,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // when RNDIS is enabled public Tethering(Context context, INetworkManagementService nmService, - INetworkStatsService statsService, Looper looper) { + INetworkStatsService statsService, IConnectivityManager connService, Looper looper) { mContext = context; mNMService = nmService; mStatsService = statsService; + mConnService = connService; mLooper = looper; mIfaces = new HashMap<String, TetherInterfaceSM>(); @@ -347,10 +349,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } private void sendTetherStateChangedBroadcast() { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); try { - if (!cm.isTetheringSupported()) return; + if (!mConnService.isTetheringSupported()) return; } catch (RemoteException e) { return; } @@ -910,6 +910,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { try { mNMService.tetherInterface(mIfaceName); } catch (Exception e) { + Log.e(TAG, "Error Tethering: " + e.toString()); setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); transitionTo(mInitialState); @@ -987,6 +988,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { try { mNMService.enableNat(mIfaceName, newUpstreamIfaceName); } catch (Exception e) { + Log.e(TAG, "Exception enabling Nat: " + e.toString()); try { mNMService.untetherInterface(mIfaceName); } catch (Exception ee) {} @@ -1150,13 +1152,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { boolean retValue = true; if (apnType == ConnectivityManager.TYPE_NONE) return false; if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection(); - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int result = Phone.APN_REQUEST_FAILED; String enableString = enableString(apnType); if (enableString == null) return false; try { - result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, + result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, enableString, new Binder()); } catch (Exception e) { } @@ -1178,10 +1178,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected boolean turnOffUpstreamMobileConnection() { if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); try { - cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, + mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, enableString(mMobileApnReserved)); } catch (Exception e) { return false; @@ -1234,8 +1232,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected void chooseUpstreamType(boolean tryCell) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int upType = ConnectivityManager.TYPE_NONE; String iface = null; @@ -1251,7 +1247,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { for (Integer netType : mUpstreamIfaceTypes) { NetworkInfo info = null; try { - info = cm.getNetworkInfo(netType.intValue()); + info = mConnService.getNetworkInfo(netType.intValue()); } catch (RemoteException e) { } if ((info != null) && info.isConnected()) { upType = netType.intValue(); @@ -1283,7 +1279,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } else { LinkProperties linkProperties = null; try { - linkProperties = cm.getLinkProperties(upType); + linkProperties = mConnService.getLinkProperties(upType); } catch (RemoteException e) { } if (linkProperties != null) iface = linkProperties.getInterfaceName(); } |