Skip to content

Commit 3b28e9a

Browse files
author
Robert Greenwalt
committed
Start using IP tool for advanced routing.
bug:5495862 bug:5396842 Change-Id: I5e31b352b14a4dc746cacce4d61cf8d9ad7382a0
1 parent 8c49b81 commit 3b28e9a

File tree

4 files changed

+120
-52
lines changed

4 files changed

+120
-52
lines changed

core/java/android/os/INetworkManagementService.aidl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ interface INetworkManagementService
104104
*/
105105
void removeRoute(String iface, in RouteInfo route);
106106

107+
/**
108+
* Add the specified route to a secondary interface
109+
* This will go into a special route table to be accessed
110+
* via ip rules
111+
*/
112+
void addSecondaryRoute(String iface, in RouteInfo route);
113+
114+
/**
115+
* Remove the specified secondary route.
116+
*/
117+
void removeSecondaryRoute(String iface, in RouteInfo route);
118+
107119
/**
108120
* Shuts down the service
109121
*/

services/java/com/android/server/ConnectivityService.java

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
171171
private static final int ENABLED = 1;
172172
private static final int DISABLED = 0;
173173

174+
private static final boolean ADD = true;
175+
private static final boolean REMOVE = false;
176+
177+
private static final boolean TO_DEFAULT_TABLE = true;
178+
private static final boolean TO_SECONDARY_TABLE = false;
179+
174180
// Share the event space with NetworkStateTracker (which can't see this
175181
// internal class but sends us events). If you change these, change
176182
// NetworkStateTracker.java too.
@@ -501,7 +507,7 @@ public ConnectivityService(Context context, INetworkManagementService netd,
501507
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
502508
INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
503509

504-
mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
510+
mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper());
505511
mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
506512
mTethering.getTetherableWifiRegexs().length != 0 ||
507513
mTethering.getTetherableBluetoothRegexs().length != 0) &&
@@ -1146,23 +1152,24 @@ public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
11461152
return false;
11471153
}
11481154

1149-
private boolean addRoute(LinkProperties p, RouteInfo r) {
1150-
return modifyRoute(p.getInterfaceName(), p, r, 0, true);
1155+
private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
1156+
return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
11511157
}
11521158

1153-
private boolean removeRoute(LinkProperties p, RouteInfo r) {
1154-
return modifyRoute(p.getInterfaceName(), p, r, 0, false);
1159+
private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
1160+
return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
11551161
}
11561162

11571163
private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
1158-
return modifyRouteToAddress(lp, addr, true);
1164+
return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE);
11591165
}
11601166

11611167
private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
1162-
return modifyRouteToAddress(lp, addr, false);
1168+
return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE);
11631169
}
11641170

1165-
private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
1171+
private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
1172+
boolean toDefaultTable) {
11661173
RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
11671174
if (bestRoute == null) {
11681175
bestRoute = RouteInfo.makeHostRoute(addr);
@@ -1176,15 +1183,15 @@ private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolea
11761183
bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
11771184
}
11781185
}
1179-
return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
1186+
return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
11801187
}
11811188

11821189
private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
1183-
boolean doAdd) {
1190+
boolean doAdd, boolean toDefaultTable) {
11841191
if ((ifaceName == null) || (lp == null) || (r == null)) return false;
11851192

11861193
if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
1187-
loge("Error adding route - too much recursion");
1194+
loge("Error modifying route - too much recursion");
11881195
return false;
11891196
}
11901197

@@ -1199,14 +1206,18 @@ private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, in
11991206
// route to it's gateway
12001207
bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
12011208
}
1202-
modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
1209+
modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
12031210
}
12041211
}
12051212
if (doAdd) {
12061213
if (VDBG) log("Adding " + r + " for interface " + ifaceName);
1207-
mAddedRoutes.add(r);
12081214
try {
1209-
mNetd.addRoute(ifaceName, r);
1215+
if (toDefaultTable) {
1216+
mAddedRoutes.add(r); // only track default table - only one apps can effect
1217+
mNetd.addRoute(ifaceName, r);
1218+
} else {
1219+
mNetd.addSecondaryRoute(ifaceName, r);
1220+
}
12101221
} catch (Exception e) {
12111222
// never crash - catch them all
12121223
if (VDBG) loge("Exception trying to add a route: " + e);
@@ -1215,18 +1226,29 @@ private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, in
12151226
} else {
12161227
// if we remove this one and there are no more like it, then refcount==0 and
12171228
// we can remove it from the table
1218-
mAddedRoutes.remove(r);
1219-
if (mAddedRoutes.contains(r) == false) {
1229+
if (toDefaultTable) {
1230+
mAddedRoutes.remove(r);
1231+
if (mAddedRoutes.contains(r) == false) {
1232+
if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1233+
try {
1234+
mNetd.removeRoute(ifaceName, r);
1235+
} catch (Exception e) {
1236+
// never crash - catch them all
1237+
if (VDBG) loge("Exception trying to remove a route: " + e);
1238+
return false;
1239+
}
1240+
} else {
1241+
if (VDBG) log("not removing " + r + " as it's still in use");
1242+
}
1243+
} else {
12201244
if (VDBG) log("Removing " + r + " for interface " + ifaceName);
12211245
try {
1222-
mNetd.removeRoute(ifaceName, r);
1246+
mNetd.removeSecondaryRoute(ifaceName, r);
12231247
} catch (Exception e) {
12241248
// never crash - catch them all
12251249
if (VDBG) loge("Exception trying to remove a route: " + e);
12261250
return false;
12271251
}
1228-
} else {
1229-
if (VDBG) log("not removing " + r + " as it's still in use");
12301252
}
12311253
}
12321254
return true;
@@ -1862,14 +1884,21 @@ private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
18621884

18631885
for (RouteInfo r : routeDiff.removed) {
18641886
if (isLinkDefault || ! r.isDefaultRoute()) {
1865-
removeRoute(curLp, r);
1887+
removeRoute(curLp, r, TO_DEFAULT_TABLE);
1888+
}
1889+
if (isLinkDefault == false) {
1890+
// remove from a secondary route table
1891+
removeRoute(curLp, r, TO_SECONDARY_TABLE);
18661892
}
18671893
}
18681894

18691895
for (RouteInfo r : routeDiff.added) {
18701896
if (isLinkDefault || ! r.isDefaultRoute()) {
1871-
addRoute(newLp, r);
1897+
addRoute(newLp, r, TO_DEFAULT_TABLE);
18721898
} else {
1899+
// add to a secondary route table
1900+
addRoute(newLp, r, TO_SECONDARY_TABLE);
1901+
18731902
// many radios add a default route even when we don't want one.
18741903
// remove the default route unless somebody else has asked for it
18751904
String ifaceName = newLp.getInterfaceName();
@@ -2450,12 +2479,6 @@ public boolean isTetheringSupported() {
24502479
int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
24512480
boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
24522481
Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
2453-
// Short term disabling of Tethering if DUN is required.
2454-
// TODO - fix multi-connection tethering using policy-base routing
2455-
int[] upstreamConnTypes = mTethering.getUpstreamIfaceTypes();
2456-
for (int i : upstreamConnTypes) {
2457-
if (i == ConnectivityManager.TYPE_MOBILE_DUN) return false;
2458-
}
24592482
return tetherEnabledInSettings && mTetheringConfigValid;
24602483
}
24612484

services/java/com/android/server/NetworkManagementService.java

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@
5959
import java.io.PrintWriter;
6060
import java.net.Inet4Address;
6161
import java.net.InetAddress;
62+
import java.net.InterfaceAddress;
63+
import java.net.NetworkInterface;
64+
import java.net.SocketException;
6265
import java.util.ArrayList;
66+
import java.util.Collection;
6367
import java.util.HashSet;
6468
import java.util.NoSuchElementException;
6569
import java.util.StringTokenizer;
@@ -77,6 +81,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
7781
private static final int ADD = 1;
7882
private static final int REMOVE = 2;
7983

84+
private static final String DEFAULT = "default";
85+
private static final String SECONDARY = "secondary";
86+
8087
/**
8188
* Name representing {@link #setGlobalAlert(long)} limit when delivered to
8289
* {@link INetworkManagementEventObserver#limitReached(String, String)}.
@@ -500,28 +507,38 @@ public void disableIpv6(String iface) throws IllegalStateException {
500507

501508
public void addRoute(String interfaceName, RouteInfo route) {
502509
mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
503-
modifyRoute(interfaceName, ADD, route);
510+
modifyRoute(interfaceName, ADD, route, DEFAULT);
504511
}
505512

506513
public void removeRoute(String interfaceName, RouteInfo route) {
507514
mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
508-
modifyRoute(interfaceName, REMOVE, route);
515+
modifyRoute(interfaceName, REMOVE, route, DEFAULT);
516+
}
517+
518+
public void addSecondaryRoute(String interfaceName, RouteInfo route) {
519+
mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
520+
modifyRoute(interfaceName, ADD, route, SECONDARY);
509521
}
510522

511-
private void modifyRoute(String interfaceName, int action, RouteInfo route) {
523+
public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
524+
mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
525+
modifyRoute(interfaceName, REMOVE, route, SECONDARY);
526+
}
527+
528+
private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) {
512529
ArrayList<String> rsp;
513530

514531
StringBuilder cmd;
515532

516533
switch (action) {
517534
case ADD:
518535
{
519-
cmd = new StringBuilder("interface route add " + interfaceName);
536+
cmd = new StringBuilder("interface route add " + interfaceName + " " + type);
520537
break;
521538
}
522539
case REMOVE:
523540
{
524-
cmd = new StringBuilder("interface route remove " + interfaceName);
541+
cmd = new StringBuilder("interface route remove " + interfaceName + " " + type);
525542
break;
526543
}
527544
default:
@@ -828,14 +845,33 @@ public String[] getDnsForwarders() throws IllegalStateException {
828845
}
829846
}
830847

848+
private void modifyNat(String cmd, String internalInterface, String externalInterface)
849+
throws SocketException {
850+
cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface);
851+
852+
NetworkInterface internalNetworkInterface =
853+
NetworkInterface.getByName(internalInterface);
854+
Collection<InterfaceAddress>interfaceAddresses =
855+
internalNetworkInterface.getInterfaceAddresses();
856+
cmd += " " + interfaceAddresses.size();
857+
for (InterfaceAddress ia : interfaceAddresses) {
858+
InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
859+
ia.getNetworkPrefixLength());
860+
cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
861+
}
862+
863+
mConnector.doCommand(cmd);
864+
}
865+
831866
public void enableNat(String internalInterface, String externalInterface)
832867
throws IllegalStateException {
833868
mContext.enforceCallingOrSelfPermission(
834869
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
870+
if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")");
835871
try {
836-
mConnector.doCommand(
837-
String.format("nat enable %s %s", internalInterface, externalInterface));
838-
} catch (NativeDaemonConnectorException e) {
872+
modifyNat("enable", internalInterface, externalInterface);
873+
} catch (Exception e) {
874+
Log.e(TAG, "enableNat got Exception " + e.toString());
839875
throw new IllegalStateException(
840876
"Unable to communicate to native daemon for enabling NAT interface");
841877
}
@@ -845,10 +881,11 @@ public void disableNat(String internalInterface, String externalInterface)
845881
throws IllegalStateException {
846882
mContext.enforceCallingOrSelfPermission(
847883
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
884+
if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")");
848885
try {
849-
mConnector.doCommand(
850-
String.format("nat disable %s %s", internalInterface, externalInterface));
851-
} catch (NativeDaemonConnectorException e) {
886+
modifyNat("disable", internalInterface, externalInterface);
887+
} catch (Exception e) {
888+
Log.e(TAG, "disableNat got Exception " + e.toString());
852889
throw new IllegalStateException(
853890
"Unable to communicate to native daemon for disabling NAT interface");
854891
}

0 commit comments

Comments
 (0)