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
Merged-In: I6e84b14872d38a897eb6a10fd37d816ec7e6da64
Change-Id: I6e84b14872d38a897eb6a10fd37d816ec7e6da64
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index cc3b49c..144d24f 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::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 @@
     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) {
+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 (rule.srcL2Address.size() != sizeof(hdr.h_source)) {
+        return Error(ENXIO) << "Invalid L2 src address length " << rule.srcL2Address.size();
+    }
+    if (rule.dstL2Address.size() != sizeof(hdr.h_dest)) {
+        return Error(ENXIO) << "Invalid L2 dst address length " << rule.dstL2Address.size();
+    }
+    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),
     };
-    if (ipAddress.size() != sizeof(in6_addr)) {
-        return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
-    }
-    if (srcL2Address.size() != sizeof(hdr.h_source)) {
-        return Error(EINVAL) << "Invalid L2 src address length " << srcL2Address.size();
-    }
-    if (dstL2Address.size() != sizeof(hdr.h_dest)) {
-        return Error(EINVAL) << "Invalid L2 dst address length " << dstL2Address.size();
-    }
-    memcpy(&hdr.h_dest, dstL2Address.data(), sizeof(hdr.h_dest));
-    memcpy(&hdr.h_source, srcL2Address.data(), sizeof(hdr.h_source));
+    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);