Fix tethering in the case of a regular upstream connection.
Fixes tethering via Ethernet, Bluetooth and WiFi (hotspot).
Tethering when the upstream has a DUN-specific APN is likely still broken
(untested).
For now, assign a fixed NetId (a hack) until we can change the framework to
create a valid NetworkAgent and all that jazz.
Bug: 15968336
Bug: 14988803
Change-Id: Idcf4d492d9329a9c87913e27be6dd835a792bea2
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index d33c47c..8efbda4 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -42,7 +42,7 @@
const uint32_t RULE_PRIORITY_OUTPUT_INTERFACE = 14000;
const uint32_t RULE_PRIORITY_LEGACY_SYSTEM = 15000;
const uint32_t RULE_PRIORITY_LEGACY_NETWORK = 16000;
-// const uint32_t RULE_PRIORITY_LOCAL_NETWORK = 17000;
+const uint32_t RULE_PRIORITY_LOCAL_NETWORK = 17000;
// const uint32_t RULE_PRIORITY_TETHERING = 18000;
const uint32_t RULE_PRIORITY_IMPLICIT_NETWORK = 19000;
// const uint32_t RULE_PRIORITY_BYPASSABLE_VPN = 20000;
@@ -542,6 +542,38 @@
fwmark.intValue, mask.intValue, OIF_NONE, INVALID_UID, INVALID_UID);
}
+// A rule to allow local network routes to override the default network.
+WARN_UNUSED_RESULT int modifyLocalOverrideRule(uint32_t table, bool add) {
+ Fwmark fwmark;
+ Fwmark mask;
+
+ fwmark.explicitlySelected = false;
+ mask.explicitlySelected = true;
+
+ return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_LOCAL_NETWORK, table,
+ fwmark.intValue, mask.intValue, OIF_NONE, INVALID_UID, INVALID_UID);
+}
+
+WARN_UNUSED_RESULT int modifyLocalNetwork(unsigned netId, const char* interface, bool add) {
+ uint32_t table = getRouteTableForInterface(interface);
+ if (table == RT_TABLE_UNSPEC) {
+ return -ESRCH;
+ }
+
+ if (int ret = modifyIncomingPacketMark(netId, interface, PERMISSION_NONE, add)) {
+ return ret;
+ }
+ if (int ret = modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, INVALID_UID, INVALID_UID,
+ add)) {
+ return ret;
+ }
+ if (int ret = modifyOutputInterfaceRule(interface, table, PERMISSION_NONE, INVALID_UID,
+ INVALID_UID, add)) {
+ return ret;
+ }
+ return modifyLocalOverrideRule(table, add);
+}
+
WARN_UNUSED_RESULT int modifyPhysicalNetwork(unsigned netId, const char* interface,
Permission permission, bool add) {
uint32_t table = getRouteTableForInterface(interface);
@@ -714,6 +746,25 @@
return 0;
}
+int RouteController::addInterfaceToLocalNetwork(unsigned netId, const char* interface) {
+ if (int ret = modifyLocalNetwork(netId, interface, ACTION_ADD)) {
+ return ret;
+ }
+ updateTableNamesFile();
+ return 0;
+}
+
+int RouteController::removeInterfaceFromLocalNetwork(unsigned netId, const char* interface) {
+ if (int ret = modifyLocalNetwork(netId, interface, ACTION_DEL)) {
+ return ret;
+ }
+ if (int ret = flushRoutes(interface)) {
+ return ret;
+ }
+ updateTableNamesFile();
+ return 0;
+}
+
int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* interface,
Permission permission) {
if (int ret = modifyPhysicalNetwork(netId, interface, permission, ACTION_ADD)) {