Start using IP tool for advanced routing.
bug:5495862 bug:5396842 Change-Id: I5e31b352b14a4dc746cacce4d61cf8d9ad7382a0
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)}.
|
||||
@ -500,15 +507,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);
|
||||
}
|
||||
|
||||
private void modifyRoute(String interfaceName, int action, RouteInfo route) {
|
||||
public void addSecondaryRoute(String interfaceName, RouteInfo route) {
|
||||
mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
|
||||
modifyRoute(interfaceName, ADD, route, SECONDARY);
|
||||
}
|
||||
|
||||
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;
|
||||
@ -516,12 +533,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:
|
||||
@ -828,14 +845,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");
|
||||
}
|
||||
@ -845,10 +881,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");
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user