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/tests/binder_test.cpp b/tests/binder_test.cpp
index 4f6fc07..0b87715 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -93,6 +93,7 @@
 using android::net::InterfaceConfigurationParcel;
 using android::net::InterfaceController;
 using android::net::MarkMaskParcel;
+using android::net::TetherOffloadRuleParcel;
 using android::net::TetherStatsParcel;
 using android::net::TunInterface;
 using android::net::UidRangeParcel;
@@ -3372,7 +3373,26 @@
     EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
 }
 
-TEST_F(BinderTest, TetherRuleDownstreamIpv6) {
+namespace {
+
+TetherOffloadRuleParcel makeTetherOffloadRule(int inputInterfaceIndex, int outputInterfaceIndex,
+                                              const std::vector<uint8_t>& destination,
+                                              int prefixLength,
+                                              const std::vector<uint8_t>& srcL2Address,
+                                              const std::vector<uint8_t>& dstL2Address) {
+    android::net::TetherOffloadRuleParcel parcel;
+    parcel.inputInterfaceIndex = inputInterfaceIndex;
+    parcel.outputInterfaceIndex = outputInterfaceIndex;
+    parcel.destination = destination;
+    parcel.prefixLength = prefixLength;
+    parcel.srcL2Address = srcL2Address;
+    parcel.dstL2Address = dstL2Address;
+    return parcel;
+}
+
+}  // namespace
+
+TEST_F(BinderTest, TetherOffloadRule) {
     SKIP_IF_BPF_NOT_SUPPORTED;
 
     // TODO: Perhaps verify invalid interface index once the netd handle the error in methods.
@@ -3389,33 +3409,56 @@
     const std::vector<uint8_t> kInvalidMac = {0xde, 0xad, 0xbe, 0xef};    // should be 6-byte length
 
     // Invalid IP address, add rule
-    auto status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kInvalidAddr4 /*bad*/,
-                                                     kSrcMac, kDstMac);
+    TetherOffloadRuleParcel rule = makeTetherOffloadRule(
+            kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac, kDstMac);
+    auto status = mNetd->tetherOffloadRuleAdd(rule);
     EXPECT_FALSE(status.isOk());
-    EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+    EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode());
 
     // Invalid source L2 address, add rule
-    status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kInvalidMac /*bad*/,
-                                                kDstMac);
+    rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kInvalidMac /*bad*/, kDstMac);
+    status = mNetd->tetherOffloadRuleAdd(rule);
     EXPECT_FALSE(status.isOk());
-    EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+    EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode());
 
     // Invalid destination L2 address, add rule
-    status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kSrcMac,
-                                                kInvalidMac /*bad*/);
+    rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kInvalidMac /*bad*/);
+    status = mNetd->tetherOffloadRuleAdd(rule);
     EXPECT_FALSE(status.isOk());
-    EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+    EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode());
 
     // Invalid IP address, remove rule
-    status = mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceExt, kInvalidAddr4 /*bad*/);
+    rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac,
+                                 kDstMac);
+    status = mNetd->tetherOffloadRuleRemove(rule);
+    EXPECT_FALSE(status.isOk());
+    EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode());
+
+    // Invalid prefix length
+    rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 64 /*bad*/, kSrcMac, kDstMac);
+    status = mNetd->tetherOffloadRuleAdd(rule);
+    EXPECT_FALSE(status.isOk());
+    EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+    status = mNetd->tetherOffloadRuleRemove(rule);
     EXPECT_FALSE(status.isOk());
     EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
 
+    // Invalid interface index
+    rule = makeTetherOffloadRule(kIfaceExt, 0, kAddr6, 128, kSrcMac, kDstMac);
+    status = mNetd->tetherOffloadRuleAdd(rule);
+    EXPECT_FALSE(status.isOk());
+    EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode());
+    rule = makeTetherOffloadRule(0, kIfaceInt, kAddr6, 64, kSrcMac, kDstMac);
+    status = mNetd->tetherOffloadRuleRemove(rule);
+    EXPECT_FALSE(status.isOk());
+    EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode());
+
     // Remove non existent rule. Expect that silently return success if the rule did not exist.
-    EXPECT_TRUE(mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceNonExistent, kAddr6).isOk());
+    rule = makeTetherOffloadRule(kIfaceNonExistent, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac);
+    EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk());
 
     // Add and remove rule normally.
-    EXPECT_TRUE(mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kSrcMac, kDstMac)
-                        .isOk());
-    EXPECT_TRUE(mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceExt, kAddr6).isOk());
+    rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac);
+    EXPECT_TRUE(mNetd->tetherOffloadRuleAdd(rule).isOk());
+    EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk());
 }