summaryrefslogtreecommitdiff
path: root/server/TetherController.cpp
diff options
context:
space:
mode:
authorRemi NGUYEN VAN <reminv@google.com>2018-03-20 14:44:12 +0900
committerRemi NGUYEN VAN <reminv@google.com>2018-03-28 12:07:32 +0900
commit3b47c793ff7ade843b1d85a9be8461c3b4dc693e (patch)
tree84c7ad9b2dd55ca013d7a23a15e331c77fc63e9d /server/TetherController.cpp
parent05827de37e5413d165bf655bdfd13e3d49c906d1 (diff)
Support adding multiple tethering upstreams.
Currently, when the first tethering interface pair is added, we add MASQUERADE rules for the upstream and IPv6 counting rules. Continue to add IPv6 counting rules when the first interface pair is added, but change the code to add MASQUERADE rules every time a new upstream is added. This will allow us to support adding, say, v4-rmnet_data0 as an upstream once we're already using rmnet_data0 as an upstream. Bug: 38218697 Bug: 64382985 Bug: 64976379 Bug: 64995262 Bug: 64380515 Test: netd_unit_test passes, manual: IPv4 or 464xlat tethering works Change-Id: I84078b2241214b3b993ccaf2e590406018df00ff
Diffstat (limited to 'server/TetherController.cpp')
-rw-r--r--server/TetherController.cpp145
1 files changed, 108 insertions, 37 deletions
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index c1d73081..6e805f56 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -138,7 +138,7 @@ TetherController::~TetherController() {
mInterfaces.clear();
mDnsForwarders.clear();
mForwardingRequests.clear();
- ifacePairList.clear();
+ mFwdIfaces.clear();
}
bool TetherController::setIpFwdEnabled() {
@@ -439,7 +439,7 @@ int TetherController::setupIptablesHooks() {
return res;
}
- ifacePairList.clear();
+ mFwdIfaces.clear();
return 0;
}
@@ -472,8 +472,6 @@ int TetherController::setDefaults() {
return res;
}
- natCount = 0;
-
return 0;
}
@@ -492,48 +490,127 @@ int TetherController::enableNat(const char* intIface, const char* extIface) {
return -1;
}
- // add this if we are the first added nat
- if (natCount == 0) {
+ if (isForwardingPairEnabled(intIface, extIface)) {
+ return 0;
+ }
+
+ // add this if we are the first enabled nat for this upstream
+ if (!isAnyForwardingEnabledOnUpstream(extIface)) {
std::vector<std::string> v4Cmds = {
"*nat",
StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
"COMMIT\n"
};
- /*
- * IPv6 tethering doesn't need the state-based conntrack rules, so
- * it unconditionally jumps to the tether counters chain all the time.
- */
- std::vector<std::string> v6Cmds = {
- "*filter",
- StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN),
- "COMMIT\n"
- };
-
if (iptablesRestoreFunction(V4, Join(v4Cmds, '\n'), nullptr) ||
- iptablesRestoreFunction(V6, Join(v6Cmds, '\n'), nullptr)) {
+ setupIPv6CountersChain()) {
ALOGE("Error setting postroute rule: iface=%s", extIface);
- // unwind what's been done, but don't care about success - what more could we do?
- setDefaults();
+ if (!isAnyForwardingPairEnabled()) {
+ // unwind what's been done, but don't care about success - what more could we do?
+ setDefaults();
+ }
return -1;
}
}
if (setForwardRules(true, intIface, extIface) != 0) {
ALOGE("Error setting forward rules");
- if (natCount == 0) {
+ if (!isAnyForwardingPairEnabled()) {
setDefaults();
}
errno = ENODEV;
return -1;
}
- natCount++;
return 0;
}
-bool TetherController::checkTetherCountingRuleExist(const std::string& pair_name) {
- return std::find(ifacePairList.begin(), ifacePairList.end(), pair_name) != ifacePairList.end();
+int TetherController::setupIPv6CountersChain() {
+ // Only add this if we are the first enabled nat
+ if (isAnyForwardingPairEnabled()) {
+ return 0;
+ }
+
+ /*
+ * IPv6 tethering doesn't need the state-based conntrack rules, so
+ * it unconditionally jumps to the tether counters chain all the time.
+ */
+ std::vector<std::string> v6Cmds = {
+ "*filter",
+ StringPrintf("-A %s -g %s", LOCAL_FORWARD, LOCAL_TETHER_COUNTERS_CHAIN),
+ "COMMIT\n"
+ };
+
+ return iptablesRestoreFunction(V6, Join(v6Cmds, '\n'), nullptr);
+}
+
+// Gets a pointer to the ForwardingDownstream for an interface pair in the map, or nullptr
+TetherController::ForwardingDownstream* TetherController::findForwardingDownstream(
+ const std::string& intIface, const std::string& extIface) {
+ auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
+ for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
+ if (it->second.iface == intIface) {
+ return &(it->second);
+ }
+ }
+ return nullptr;
+}
+
+void TetherController::addForwardingPair(const std::string& intIface, const std::string& extIface) {
+ ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
+ if (existingEntry != nullptr) {
+ existingEntry->active = true;
+ return;
+ }
+
+ mFwdIfaces.insert(std::pair<std::string, ForwardingDownstream>(extIface, {
+ .iface = intIface,
+ .active = true
+ }));
+}
+
+void TetherController::markForwardingPairDisabled(
+ const std::string& intIface, const std::string& extIface) {
+ ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
+ if (existingEntry == nullptr) {
+ return;
+ }
+
+ existingEntry->active = false;
+}
+
+bool TetherController::isForwardingPairEnabled(
+ const std::string& intIface, const std::string& extIface) {
+ ForwardingDownstream* existingEntry = findForwardingDownstream(intIface, extIface);
+ return existingEntry != nullptr && existingEntry->active;
+}
+
+bool TetherController::isAnyForwardingEnabledOnUpstream(const std::string& extIface) {
+ auto extIfaceMatches = mFwdIfaces.equal_range(extIface);
+ for (auto it = extIfaceMatches.first; it != extIfaceMatches.second; ++it) {
+ if (it->second.active) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TetherController::isAnyForwardingPairEnabled() {
+ for (auto& it : mFwdIfaces) {
+ if (it.second.active) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TetherController::tetherCountingRuleExists(
+ const std::string& iface1, const std::string& iface2) {
+ // A counting rule exists if NAT was ever enabled for this interface pair, so if the pair
+ // is in the map regardless of its active status. Rules are added both ways so we check with
+ // the 2 combinations.
+ return findForwardingDownstream(iface1, iface2) != nullptr
+ || findForwardingDownstream(iface2, iface1) != nullptr;
}
/* static */
@@ -566,15 +643,11 @@ int TetherController::setForwardRules(bool add, const char *intIface, const char
"*filter",
};
- /* We only ever add tethering quota rules so that they stick. */
- std::string pair1 = StringPrintf("%s_%s", intIface, extIface);
- if (add && !checkTetherCountingRuleExist(pair1)) {
+ // We only ever add tethering quota rules so that they stick.
+ if (add && !tetherCountingRuleExists(intIface, extIface)) {
v4.push_back(makeTetherCountingRule(intIface, extIface));
- v6.push_back(makeTetherCountingRule(intIface, extIface));
- }
- std::string pair2 = StringPrintf("%s_%s", extIface, intIface);
- if (add && !checkTetherCountingRuleExist(pair2)) {
v4.push_back(makeTetherCountingRule(extIface, intIface));
+ v6.push_back(makeTetherCountingRule(intIface, extIface));
v6.push_back(makeTetherCountingRule(extIface, intIface));
}
@@ -599,11 +672,10 @@ int TetherController::setForwardRules(bool add, const char *intIface, const char
return -1;
}
- if (add && !checkTetherCountingRuleExist(pair1)) {
- ifacePairList.push_front(pair1);
- }
- if (add && !checkTetherCountingRuleExist(pair2)) {
- ifacePairList.push_front(pair2);
+ if (add) {
+ addForwardingPair(intIface, extIface);
+ } else {
+ markForwardingPairDisabled(intIface, extIface);
}
return 0;
@@ -616,8 +688,7 @@ int TetherController::disableNat(const char* intIface, const char* extIface) {
}
setForwardRules(false, intIface, extIface);
- if (--natCount <= 0) {
- // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
+ if (!isAnyForwardingPairEnabled()) {
setDefaults();
}
return 0;