summaryrefslogtreecommitdiff
path: root/server/TetherController.cpp
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2020-04-04 00:44:01 +0900
committerLorenzo Colitti <lorenzo@google.com>2020-04-06 09:25:06 +0900
commit182cd3c8f0f3637288ff07ccd64e77c96afc3a0a (patch)
tree19094ae136fc9f46a99f49883a53b232d94f7626 /server/TetherController.cpp
parentecd5bf4633fe1fce0ff5503862e6be0e51bec686 (diff)
Convert tethering offload IPCs from primitive args to a parcel.
Defining stable AIDL IPCs with primitive args is not future-proof because AIDL does not support method overloading, so any time a parameter is added a new method needs to be created. It's better to use parcelables for parameters instead, because parcelables can be extended in subsequent version. Define a TetherOffloadRuleParcel data structure to represent tethering offload rules, and switch the tethering offload IPCs to it before we freeze the INetd AIDL. Bug: 140541991 Test: atest netd_integration_test Change-Id: I6e84b14872d38a897eb6a10fd37d816ec7e6da64
Diffstat (limited to 'server/TetherController.cpp')
-rw-r--r--server/TetherController.cpp69
1 files changed, 44 insertions, 25 deletions
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index cc3b49c0..144d24f4 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -55,6 +55,8 @@
#include "Permission.h"
#include "TetherController.h"
+#include "android/net/TetherOffloadRuleParcel.h"
+
namespace android {
namespace net {
@@ -65,6 +67,7 @@ using android::base::Result;
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::unique_fd;
+using android::net::TetherOffloadRuleParcel;
using android::netdutils::DumpWriter;
using android::netdutils::ScopedIndent;
using android::netdutils::statusFromErrno;
@@ -821,47 +824,63 @@ int TetherController::disableNat(const char* intIface, const char* extIface) {
return 0;
}
-Result<void> TetherController::addDownstreamIpv6Rule(int intIfaceIndex, int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress,
- const std::vector<uint8_t>& srcL2Address,
- const std::vector<uint8_t>& dstL2Address) {
- ethhdr hdr = {
- .h_proto = htons(ETH_P_IPV6),
- };
- if (ipAddress.size() != sizeof(in6_addr)) {
- return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
+namespace {
+Result<void> validateOffloadRule(const TetherOffloadRuleParcel& rule) {
+ struct ethhdr hdr;
+
+ if (rule.inputInterfaceIndex <= 0) {
+ return Error(ENODEV) << "Invalid input interface " << rule.inputInterfaceIndex;
+ }
+ if (rule.outputInterfaceIndex <= 0) {
+ return Error(ENODEV) << "Invalid output interface " << rule.inputInterfaceIndex;
+ }
+ if (rule.prefixLength != 128) {
+ return Error(EINVAL) << "Prefix length must be 128, not " << rule.prefixLength;
+ }
+ if (rule.destination.size() != sizeof(in6_addr)) {
+ return Error(EAFNOSUPPORT) << "Invalid IP address length " << rule.destination.size();
}
- if (srcL2Address.size() != sizeof(hdr.h_source)) {
- return Error(EINVAL) << "Invalid L2 src address length " << srcL2Address.size();
+ if (rule.srcL2Address.size() != sizeof(hdr.h_source)) {
+ return Error(ENXIO) << "Invalid L2 src address length " << rule.srcL2Address.size();
}
- if (dstL2Address.size() != sizeof(hdr.h_dest)) {
- return Error(EINVAL) << "Invalid L2 dst address length " << dstL2Address.size();
+ if (rule.dstL2Address.size() != sizeof(hdr.h_dest)) {
+ return Error(ENXIO) << "Invalid L2 dst address length " << rule.dstL2Address.size();
}
- memcpy(&hdr.h_dest, dstL2Address.data(), sizeof(hdr.h_dest));
- memcpy(&hdr.h_source, srcL2Address.data(), sizeof(hdr.h_source));
+ return Result<void>();
+}
+} // namespace
+
+Result<void> TetherController::addOffloadRule(const TetherOffloadRuleParcel& rule) {
+ Result<void> res = validateOffloadRule(rule);
+ if (!res.ok()) return res;
+
+ ethhdr hdr = {
+ .h_proto = htons(ETH_P_IPV6),
+ };
+ memcpy(&hdr.h_dest, rule.dstL2Address.data(), sizeof(hdr.h_dest));
+ memcpy(&hdr.h_source, rule.srcL2Address.data(), sizeof(hdr.h_source));
+ // Only downstream supported for now.
TetherIngressKey key = {
- .iif = static_cast<uint32_t>(extIfaceIndex),
- .neigh6 = *(const in6_addr*)ipAddress.data(),
+ .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
+ .neigh6 = *(const in6_addr*)rule.destination.data(),
};
TetherIngressValue value = {
- static_cast<uint32_t>(intIfaceIndex),
+ static_cast<uint32_t>(rule.outputInterfaceIndex),
hdr,
};
return mBpfIngressMap.writeValue(key, value, BPF_ANY);
}
-Result<void> TetherController::removeDownstreamIpv6Rule(int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress) {
- if (ipAddress.size() != sizeof(in6_addr)) {
- return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
- }
+Result<void> TetherController::removeOffloadRule(const TetherOffloadRuleParcel& rule) {
+ Result<void> res = validateOffloadRule(rule);
+ if (!res.ok()) return res;
TetherIngressKey key = {
- .iif = static_cast<uint32_t>(extIfaceIndex),
- .neigh6 = *(const in6_addr*)ipAddress.data(),
+ .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
+ .neigh6 = *(const in6_addr*)rule.destination.data(),
};
Result<void> ret = mBpfIngressMap.deleteValue(key);