Network-related commands porting
Test: built, flashed, booted
system/netd/tests/runtests.sh passes
Change-Id: I14160f81050c2782301d27e622461e66b10fd070
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 1014cf9..4ed609c 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -518,8 +518,9 @@
}
TEST_F(BinderTest, NetworkInterfaces) {
- EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, "").isOk());
- EXPECT_EQ(EEXIST, mNetd->networkCreatePhysical(TEST_NETID1, "").serviceSpecificErrorCode());
+ EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk());
+ EXPECT_EQ(EEXIST, mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE)
+ .serviceSpecificErrorCode());
EXPECT_EQ(EEXIST, mNetd->networkCreateVpn(TEST_NETID1, false, true).serviceSpecificErrorCode());
EXPECT_TRUE(mNetd->networkCreateVpn(TEST_NETID2, false, true).isOk());
@@ -530,6 +531,7 @@
EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID2, sTun.name()).isOk());
EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID2).isOk());
+ EXPECT_EQ(ENONET, mNetd->networkDestroy(TEST_NETID1).serviceSpecificErrorCode());
}
TEST_F(BinderTest, NetworkUidRules) {
@@ -1467,7 +1469,7 @@
long testQuotaBytes = 5550;
// Add test physical network
- EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, "").isOk());
+ EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk());
EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk());
binder::Status status = mNetd->bandwidthSetInterfaceQuota(sTun.name(), testQuotaBytes);
@@ -1485,7 +1487,7 @@
TEST_F(BinderTest, BandwidthSetRemoveInterfaceAlert) {
long testAlertBytes = 373;
// Add test physical network
- EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, "").isOk());
+ EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk());
EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk());
// Need to have a prior interface quota set to set an alert
binder::Status status = mNetd->bandwidthSetInterfaceQuota(sTun.name(), testAlertBytes);
@@ -1549,6 +1551,270 @@
namespace {
+std::vector<std::string> listIpRoutes(const char* ipVersion, const char* table) {
+ std::string command = StringPrintf("%s %s route ls table %s", IP_PATH, ipVersion, table);
+ return runCommand(command);
+}
+
+bool ipRouteExists(const char* ipVersion, const char* table, const std::string ipRoute) {
+ std::vector<std::string> routes = listIpRoutes(ipVersion, table);
+ for (const auto& route : routes) {
+ if (route.find(ipRoute) != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void expectNetworkRouteExists(const char* ipVersion, const char* ifName, const std::string& dst,
+ const std::string& nextHop, const char* table) {
+ std::string ipNetworkRoute = {};
+ if ((dst == "0.0.0.0/0" || dst == "::/0") && nextHop.empty()) {
+ ipNetworkRoute = StringPrintf("default dev %s proto static", ifName);
+ } else if (nextHop.empty()) {
+ ipNetworkRoute = StringPrintf("%s dev %s proto static", dst.c_str(), ifName);
+ }
+
+ EXPECT_TRUE(ipRouteExists(ipVersion, table, ipNetworkRoute));
+}
+
+void expectNetworkRouteDoesNotExist(const char* ipVersion, const char* ifName,
+ const std::string& dst, const std::string& nextHop,
+ const char* table) {
+ std::string ipNetworkRoute = {};
+ if ((dst == "0.0.0.0/0" || dst == "::/0") && nextHop.empty()) {
+ ipNetworkRoute = StringPrintf("default dev %s proto static", ifName);
+ } else if (nextHop.empty()) {
+ ipNetworkRoute = StringPrintf("%s dev %s proto static", dst.c_str(), ifName);
+ }
+
+ EXPECT_FALSE(ipRouteExists(ipVersion, table, ipNetworkRoute));
+}
+
+bool ipRuleExists(const char* ipVersion, const std::string& ipRule) {
+ std::vector<std::string> rules = listIpRules(ipVersion);
+ for (const auto& rule : rules) {
+ if (rule.find(ipRule) != std::string::npos) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void expectNetworkDefaultIpRuleExists(const char* ifName) {
+ std::string networkDefaultRule =
+ StringPrintf("22000:\tfrom all fwmark 0x0/0xffff iif lo lookup %s", ifName);
+
+ for (const auto& ipVersion : {IP_RULE_V4, IP_RULE_V6}) {
+ EXPECT_TRUE(ipRuleExists(ipVersion, networkDefaultRule));
+ }
+}
+
+void expectNetworkDefaultIpRuleDoesNotExist() {
+ static const char networkDefaultRule[] = "22000:\tfrom all fwmark 0x0/0xffff iif lo";
+
+ for (const auto& ipVersion : {IP_RULE_V4, IP_RULE_V6}) {
+ EXPECT_FALSE(ipRuleExists(ipVersion, networkDefaultRule));
+ }
+}
+
+void expectNetworkPermissionIpRuleExists(const char* ifName, int permission) {
+ std::string networkPermissionRule = "";
+ switch (permission) {
+ case INetd::PERMISSION_NONE:
+ networkPermissionRule = StringPrintf(
+ "13000:\tfrom all fwmark 0x1ffdd/0x1ffff iif lo lookup %s", ifName);
+ break;
+ case INetd::PERMISSION_NETWORK:
+ networkPermissionRule = StringPrintf(
+ "13000:\tfrom all fwmark 0x5ffdd/0x5ffff iif lo lookup %s", ifName);
+ break;
+ case INetd::PERMISSION_SYSTEM:
+ networkPermissionRule = StringPrintf(
+ "13000:\tfrom all fwmark 0xdffdd/0xdffff iif lo lookup %s", ifName);
+ break;
+ }
+
+ for (const auto& ipVersion : {IP_RULE_V4, IP_RULE_V6}) {
+ EXPECT_TRUE(ipRuleExists(ipVersion, networkPermissionRule));
+ }
+}
+
+// TODO: It is a duplicate function, need to remove it
+bool iptablesNetworkPermissionIptablesRuleExists(const char* binary, const char* chainName,
+ const std::string& expectedInterface,
+ const std::string& expectedRule,
+ const char* table) {
+ std::vector<std::string> rules = listIptablesRuleByTable(binary, table, chainName);
+ for (const auto& rule : rules) {
+ if (rule.find(expectedInterface) != std::string::npos) {
+ if (rule.find(expectedRule) != std::string::npos) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void expectNetworkPermissionIptablesRuleExists(const char* ifName, int permission) {
+ static const char ROUTECTRL_INPUT[] = "routectrl_mangle_INPUT";
+ std::string networkIncomingPacketMarkRule = "";
+ switch (permission) {
+ case INetd::PERMISSION_NONE:
+ networkIncomingPacketMarkRule = "MARK xset 0x3ffdd/0xffefffff";
+ break;
+ case INetd::PERMISSION_NETWORK:
+ networkIncomingPacketMarkRule = "MARK xset 0x7ffdd/0xffefffff";
+ break;
+ case INetd::PERMISSION_SYSTEM:
+ networkIncomingPacketMarkRule = "MARK xset 0xfffdd/0xffefffff";
+ break;
+ }
+
+ for (const auto& binary : {IPTABLES_PATH, IP6TABLES_PATH}) {
+ EXPECT_TRUE(iptablesNetworkPermissionIptablesRuleExists(
+ binary, ROUTECTRL_INPUT, ifName, networkIncomingPacketMarkRule, MANGLE_TABLE));
+ }
+}
+
+} // namespace
+
+TEST_F(BinderTest, NetworkAddRemoveRouteUserPermission) {
+ static const struct TestData {
+ const char* ipVersion;
+ const char* testDest;
+ const char* testNextHop;
+ const bool expectSuccess;
+ } kTestData[] = {
+ {IP_RULE_V4, "0.0.0.0/0", "", true},
+ {IP_RULE_V4, "10.152.83.112/30", "", true},
+ {IP_RULE_V4, "10.152.83.112/30", "fe80::/64", false},
+ {IP_RULE_V6, "::/0", "", true},
+ {IP_RULE_V6, "fe80::/64", "", true},
+ {IP_RULE_V4, "fe80::/64", "0.0.0.0", false},
+ };
+
+ static const char testTableLegacySystem[] = "legacy_system";
+ const int testUid = randomUid();
+ const std::vector<int32_t> testUids = {testUid};
+
+ // Add test physical network
+ EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk());
+ EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk());
+
+ for (unsigned int i = 0; i < arraysize(kTestData); i++) {
+ const auto& td = kTestData[i];
+
+ binder::Status status =
+ mNetd->networkAddRoute(TEST_NETID1, sTun.name(), td.testDest, td.testNextHop);
+ if (td.expectSuccess) {
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkRouteExists(td.ipVersion, sTun.name().c_str(), td.testDest, td.testNextHop,
+ sTun.name().c_str());
+ } else {
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
+ ASSERT_NE(0, status.serviceSpecificErrorCode());
+ }
+
+ status = mNetd->networkRemoveRoute(TEST_NETID1, sTun.name(), td.testDest, td.testNextHop);
+ if (td.expectSuccess) {
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkRouteDoesNotExist(td.ipVersion, sTun.name().c_str(), td.testDest,
+ td.testNextHop, sTun.name().c_str());
+ } else {
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
+ ASSERT_NE(0, status.serviceSpecificErrorCode());
+ }
+
+ // Add system permission for test uid
+ status = mNetd->networkSetPermissionForUser(INetd::PERMISSION_SYSTEM, testUids);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ status = mNetd->networkAddLegacyRoute(TEST_NETID1, sTun.name(), td.testDest, td.testNextHop,
+ testUid);
+ if (td.expectSuccess) {
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkRouteExists(td.ipVersion, sTun.name().c_str(), td.testDest, td.testNextHop,
+ testTableLegacySystem);
+ } else {
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
+ ASSERT_NE(0, status.serviceSpecificErrorCode());
+ }
+
+ status = mNetd->networkRemoveLegacyRoute(TEST_NETID1, sTun.name(), td.testDest,
+ td.testNextHop, testUid);
+ if (td.expectSuccess) {
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkRouteDoesNotExist(td.ipVersion, sTun.name().c_str(), td.testDest,
+ td.testNextHop, testTableLegacySystem);
+ } else {
+ ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
+ ASSERT_NE(0, status.serviceSpecificErrorCode());
+ }
+
+ // Remove system permission for test uid
+ status = mNetd->networkClearPermissionForUser(testUids);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ }
+
+ // Remove test physical network
+ EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
+}
+
+TEST_F(BinderTest, NetworkPermissionDefault) {
+ // Add test physical network
+ EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk());
+ EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk());
+
+ // Get current default netowork NetId
+ int currentNetid;
+ binder::Status status = mNetd->networkGetDefault(¤tNetid);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Test SetDefault
+ status = mNetd->networkSetDefault(TEST_NETID1);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkDefaultIpRuleExists(sTun.name().c_str());
+
+ status = mNetd->networkClearDefault();
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkDefaultIpRuleDoesNotExist();
+
+ // Add default network back
+ status = mNetd->networkSetDefault(currentNetid);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Test SetPermission
+ status = mNetd->networkSetPermissionForNetwork(TEST_NETID1, INetd::PERMISSION_SYSTEM);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkPermissionIpRuleExists(sTun.name().c_str(), INetd::PERMISSION_SYSTEM);
+ expectNetworkPermissionIptablesRuleExists(sTun.name().c_str(), INetd::PERMISSION_SYSTEM);
+
+ status = mNetd->networkSetPermissionForNetwork(TEST_NETID1, INetd::PERMISSION_NONE);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectNetworkPermissionIpRuleExists(sTun.name().c_str(), INetd::PERMISSION_NONE);
+ expectNetworkPermissionIptablesRuleExists(sTun.name().c_str(), INetd::PERMISSION_NONE);
+
+ // Remove test physical network
+ EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
+}
+
+TEST_F(BinderTest, NetworkSetProtectAllowDeny) {
+ const int testUid = randomUid();
+ binder::Status status = mNetd->networkSetProtectAllow(testUid);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ bool ret = false;
+ status = mNetd->networkCanProtect(testUid, &ret);
+ EXPECT_TRUE(ret);
+
+ status = mNetd->networkSetProtectDeny(testUid);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ status = mNetd->networkCanProtect(testUid, &ret);
+ EXPECT_FALSE(ret);
+}
+
+namespace {
+
int readIntFromPath(const std::string& path) {
std::string result = "";
EXPECT_TRUE(ReadFileToString(path, &result));
@@ -1670,4 +1936,4 @@
status = mNetd->tetherDnsList(&dnsList);
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
expectTetherDnsListEquals(dnsList, testDnsAddrs);
-}
+}
\ No newline at end of file