summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Greenwalt <rgreenwalt@google.com>2011-11-05 19:33:46 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2011-11-05 19:33:46 +0000
commit08d153fb8e3c92716405d9303cc700095308a8af (patch)
tree63898696bdf1c8a95ab2067dea4bbeead025f1f6
parentaaa0336f883b2f94af5e7d4a320cb9a351a2db93 (diff)
parentfd900f05fb67046b97701f20626f7fd408fd8990 (diff)
downloadframeworks_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.
-rw-r--r--core/java/android/os/INetworkManagementService.aidl12
-rw-r--r--services/java/com/android/server/ConnectivityService.java77
-rw-r--r--services/java/com/android/server/NetworkManagementService.java59
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java24
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();
}