summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Harold <nharold@google.com>2018-04-25 00:42:39 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2018-04-25 00:42:39 +0000
commit7c36c990943039386e40d218264d7a1d3cef4243 (patch)
treeed20ca2278efb6a85606f7e2397d1ec7fab786a9
parent883abcef8e2ea0612e2226c8e2d05ddc1fb00592 (diff)
parentf5646cde551de44ba10b61c2d5cecb414847d454 (diff)
downloadnetd-7c36c990943039386e40d218264d7a1d3cef4243.tar.gz
Merge changes from topic "netd-restart" into pi-dev
* changes: Add Functions to flush SADB, Policy DB, and Ifaces Factor getIfaceNames() from getIfaceList() Restart main when netd restarts
-rw-r--r--server/Controllers.cpp7
-rw-r--r--server/InterfaceController.cpp24
-rw-r--r--server/InterfaceController.h1
-rw-r--r--server/InterfaceControllerTest.cpp13
-rw-r--r--server/NetdNativeService.cpp1
-rw-r--r--server/XfrmController.cpp44
-rw-r--r--server/XfrmController.h82
-rw-r--r--server/netd.rc2
-rw-r--r--tests/Android.mk4
-rw-r--r--tests/binder_test.cpp69
10 files changed, 197 insertions, 50 deletions
diff --git a/server/Controllers.cpp b/server/Controllers.cpp
index b0b1925b..221a20a3 100644
--- a/server/Controllers.cpp
+++ b/server/Controllers.cpp
@@ -30,6 +30,7 @@
#include "RouteController.h"
#include "Stopwatch.h"
#include "oem_iptables_hook.h"
+#include "XfrmController.h"
namespace android {
namespace net {
@@ -279,6 +280,12 @@ void Controllers::init() {
ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
}
ALOGI("Initializing RouteController: %.1fms", s.getTimeAndReset());
+
+ netdutils::Status xStatus = XfrmController::Init();
+ if (!isOk(xStatus)) {
+ ALOGE("Failed to initialize XfrmController (%s)", netdutils::toString(xStatus).c_str());
+ };
+ ALOGI("Initializing XfrmController: %.1fms", s.getTimeAndReset());
}
Controllers* gCtls = nullptr;
diff --git a/server/InterfaceController.cpp b/server/InterfaceController.cpp
index 5a630255..c0210d7b 100644
--- a/server/InterfaceController.cpp
+++ b/server/InterfaceController.cpp
@@ -43,6 +43,7 @@ using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::net::INetd;
using android::net::RouteController;
+using android::netdutils::isOk;
using android::netdutils::Status;
using android::netdutils::StatusOr;
using android::netdutils::makeSlice;
@@ -388,8 +389,8 @@ void InterfaceController::setIPv6OptimisticMode(const char *value) {
setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
}
-StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
- std::map<std::string, uint32_t> ifacePairs;
+StatusOr<std::vector<std::string>> InterfaceController::getIfaceNames() {
+ std::vector<std::string> ifaceNames;
DIR* d;
struct dirent* de;
@@ -398,11 +399,22 @@ StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
}
while ((de = readdir(d))) {
if (de->d_name[0] == '.') continue;
- uint32_t ifaceIndex = if_nametoindex(de->d_name);
- if (ifaceIndex) {
- ifacePairs.insert(std::pair<std::string, uint32_t>(de->d_name, ifaceIndex));
- }
+ ifaceNames.push_back(std::string(de->d_name));
}
closedir(d);
+ return ifaceNames;
+}
+
+StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
+ std::map<std::string, uint32_t> ifacePairs;
+
+ ASSIGN_OR_RETURN(auto ifaceNames, getIfaceNames());
+
+ for (const auto& name : ifaceNames) {
+ uint32_t ifaceIndex = if_nametoindex(name.c_str());
+ if (ifaceIndex) {
+ ifacePairs.insert(std::pair<std::string, uint32_t>(name, ifaceIndex));
+ }
+ }
return ifacePairs;
}
diff --git a/server/InterfaceController.h b/server/InterfaceController.h
index 9a2e5e44..cd6f0eb2 100644
--- a/server/InterfaceController.h
+++ b/server/InterfaceController.h
@@ -53,6 +53,7 @@ public:
const char *family, const char *which, const char *interface, const char *parameter,
const char *value);
+ static android::netdutils::StatusOr<std::vector<std::string>> getIfaceNames();
static android::netdutils::StatusOr<std::map<std::string, uint32_t>> getIfaceList();
private:
diff --git a/server/InterfaceControllerTest.cpp b/server/InterfaceControllerTest.cpp
index 0cf7cfc1..fc5dce12 100644
--- a/server/InterfaceControllerTest.cpp
+++ b/server/InterfaceControllerTest.cpp
@@ -178,6 +178,19 @@ TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) {
class GetIfaceListTest : public testing::Test {};
+TEST_F(GetIfaceListTest, IfaceNames) {
+ StatusOr<std::vector<std::string>> ifaceNames = InterfaceController::getIfaceNames();
+ EXPECT_EQ(ok, ifaceNames.status());
+ struct ifaddrs *ifaddr, *ifa;
+ EXPECT_EQ(0, getifaddrs(&ifaddr));
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ const auto val = std::find(
+ ifaceNames.value().begin(), ifaceNames.value().end(), ifa->ifa_name);
+ EXPECT_NE(ifaceNames.value().end(), val);
+ }
+ freeifaddrs(ifaddr);
+}
+
TEST_F(GetIfaceListTest, IfaceExist) {
StatusOr<std::map<std::string, uint32_t>> ifaceMap = InterfaceController::getIfaceList();
EXPECT_EQ(ok, ifaceMap.status());
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index d953f3a2..c1e3ffa3 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -475,7 +475,6 @@ binder::Status NetdNativeService::ipSecSetEncapSocketOwner(const android::base::
return asBinderStatus(gCtls->xfrmCtrl.ipSecSetEncapSocketOwner(socket, newUid, callerUid));
}
-
binder::Status NetdNativeService::ipSecAllocateSpi(
int32_t transformId,
const std::string& sourceAddress,
diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp
index 744728a6..adc02b78 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -39,6 +39,7 @@
#include <sys/wait.h>
#include <linux/in.h>
+#include <linux/ipsec.h>
#include <linux/netlink.h>
#include <linux/xfrm.h>
@@ -47,6 +48,7 @@
#include "android-base/unique_fd.h"
#include <log/log_properties.h>
#define LOG_TAG "XfrmController"
+#include "InterfaceController.h"
#include "NetdConstants.h"
#include "NetlinkCommands.h"
#include "ResponseCode.h"
@@ -83,6 +85,9 @@ constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE;
constexpr uint32_t INVALID_SPI = 0;
+// Must match TUNNEL_INTERFACE_PREFIX in IpSecService.java
+constexpr char const* TUNNEL_INTERFACE_PREFIX = "ipsec";
+
#define XFRM_MSG_TRANS(x) \
case x: \
return #x;
@@ -370,6 +375,45 @@ private:
//
XfrmController::XfrmController(void) {}
+netdutils::Status XfrmController::Init() {
+ RETURN_IF_NOT_OK(flushInterfaces());
+ XfrmSocketImpl sock;
+ RETURN_IF_NOT_OK(sock.open());
+ RETURN_IF_NOT_OK(flushSaDb(sock));
+ return flushPolicyDb(sock);
+}
+
+netdutils::Status XfrmController::flushInterfaces() {
+ const auto& ifaces = InterfaceController::getIfaceNames();
+ RETURN_IF_NOT_OK(ifaces);
+
+ for (const std::string& iface : ifaces.value()) {
+ int status = 0;
+ // Look for the reserved interface prefix, which must be in the name at position 0
+ if (iface.find(TUNNEL_INTERFACE_PREFIX) == 0 &&
+ (status = removeVirtualTunnelInterface(iface)) < 0) {
+ ALOGE("Failed to delete ipsec tunnel %s.", iface.c_str());
+ return netdutils::statusFromErrno(status, "Failed to remove ipsec tunnel.");
+ }
+ }
+ return netdutils::status::ok;
+}
+
+netdutils::Status XfrmController::flushSaDb(const XfrmSocket& s) {
+ struct xfrm_usersa_flush flushUserSa = {.proto = IPSEC_PROTO_ANY};
+
+ std::vector<iovec> iov = {{NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
+ {&flushUserSa, sizeof(flushUserSa)}, // xfrm_usersa_flush structure
+ {kPadBytes, NLMSG_ALIGN(sizeof(flushUserSa)) - sizeof(flushUserSa)}};
+
+ return s.sendMessage(XFRM_MSG_FLUSHSA, NETLINK_REQUEST_FLAGS, 0, &iov);
+}
+
+netdutils::Status XfrmController::flushPolicyDb(const XfrmSocket& s) {
+ std::vector<iovec> iov = {{NULL, 0}}; // reserved for the eventual addition of a NLMSG_HDR
+ return s.sendMessage(XFRM_MSG_FLUSHPOLICY, NETLINK_REQUEST_FLAGS, 0, &iov);
+}
+
netdutils::Status XfrmController::ipSecSetEncapSocketOwner(const android::base::unique_fd& socket,
int newUid, uid_t callerUid) {
ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
diff --git a/server/XfrmController.h b/server/XfrmController.h
index 298fae66..f21dfa1c 100644
--- a/server/XfrmController.h
+++ b/server/XfrmController.h
@@ -125,14 +125,16 @@ class XfrmController {
public:
XfrmController();
- netdutils::Status ipSecSetEncapSocketOwner(const android::base::unique_fd& socket, int newUid,
- uid_t callerUid);
+ static netdutils::Status Init();
- netdutils::Status ipSecAllocateSpi(int32_t transformId, const std::string& localAddress,
- const std::string& remoteAddress, int32_t inSpi,
- int32_t* outSpi);
+ static netdutils::Status ipSecSetEncapSocketOwner(const android::base::unique_fd& socket,
+ int newUid, uid_t callerUid);
- netdutils::Status ipSecAddSecurityAssociation(
+ static netdutils::Status ipSecAllocateSpi(int32_t transformId, const std::string& localAddress,
+ const std::string& remoteAddress, int32_t inSpi,
+ int32_t* outSpi);
+
+ static netdutils::Status ipSecAddSecurityAssociation(
int32_t transformId, int32_t mode, const std::string& sourceAddress,
const std::string& destinationAddress, int32_t underlyingNetId, int32_t spi,
int32_t markValue, int32_t markMask, const std::string& authAlgo,
@@ -141,41 +143,43 @@ public:
const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType,
int32_t encapLocalPort, int32_t encapRemotePort);
- netdutils::Status ipSecDeleteSecurityAssociation(int32_t transformId,
- const std::string& sourceAddress,
- const std::string& destinationAddress,
- int32_t spi, int32_t markValue,
- int32_t markMask);
+ static netdutils::Status ipSecDeleteSecurityAssociation(int32_t transformId,
+ const std::string& sourceAddress,
+ const std::string& destinationAddress,
+ int32_t spi, int32_t markValue,
+ int32_t markMask);
- netdutils::Status ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
- int32_t transformId, int32_t direction,
- const std::string& localAddress,
- const std::string& remoteAddress,
- int32_t spi);
+ static netdutils::Status
+ ipSecApplyTransportModeTransform(const android::base::unique_fd& socket, int32_t transformId,
+ int32_t direction, const std::string& localAddress,
+ const std::string& remoteAddress, int32_t spi);
- netdutils::Status ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket);
+ static netdutils::Status
+ ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket);
- netdutils::Status ipSecAddSecurityPolicy(int32_t transformId, int32_t direction,
- const std::string& sourceAddress,
- const std::string& destinationAddress, int32_t spi,
- int32_t markValue, int32_t markMask);
+ static netdutils::Status ipSecAddSecurityPolicy(int32_t transformId, int32_t direction,
+ const std::string& sourceAddress,
+ const std::string& destinationAddress,
+ int32_t spi, int32_t markValue,
+ int32_t markMask);
- netdutils::Status ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction,
- const std::string& sourceAddress,
- const std::string& destinationAddress, int32_t spi,
- int32_t markValue, int32_t markMask);
+ static netdutils::Status ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction,
+ const std::string& sourceAddress,
+ const std::string& destinationAddress,
+ int32_t spi, int32_t markValue,
+ int32_t markMask);
- netdutils::Status ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction,
- const std::string& sourceAddress,
- const std::string& destinationAddress,
- int32_t markValue, int32_t markMask);
+ static netdutils::Status ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction,
+ const std::string& sourceAddress,
+ const std::string& destinationAddress,
+ int32_t markValue, int32_t markMask);
- int addVirtualTunnelInterface(const std::string& deviceName,
- const std::string& localAddress,
- const std::string& remoteAddress,
- int32_t ikey, int32_t okey, bool isUpdate);
+ static int addVirtualTunnelInterface(const std::string& deviceName,
+ const std::string& localAddress,
+ const std::string& remoteAddress, int32_t ikey,
+ int32_t okey, bool isUpdate);
- int removeVirtualTunnelInterface(const std::string& deviceName);
+ static int removeVirtualTunnelInterface(const std::string& deviceName);
// Some XFRM netlink attributes comprise a header, a struct, and some data
// after the struct. We wrap all of those in one struct for easier
@@ -323,9 +327,9 @@ private:
static netdutils::Status processSecurityPolicy(int32_t transformId, int32_t direction,
const std::string& localAddress,
- const std::string& remoteAddress,
- int32_t spi, int32_t markValue,
- int32_t markMask, int32_t msgType);
+ const std::string& remoteAddress, int32_t spi,
+ int32_t markValue, int32_t markMask,
+ int32_t msgType);
static netdutils::Status updateTunnelModeSecurityPolicy(const XfrmSaInfo& record,
const XfrmSocket& sock,
XfrmDirection direction,
@@ -333,6 +337,10 @@ private:
static netdutils::Status deleteTunnelModeSecurityPolicy(const XfrmSaInfo& record,
const XfrmSocket& sock,
XfrmDirection direction);
+ static netdutils::Status flushInterfaces();
+ static netdutils::Status flushSaDb(const XfrmSocket& s);
+ static netdutils::Status flushPolicyDb(const XfrmSocket& s);
+
// END TODO(messagerefactor)
};
diff --git a/server/netd.rc b/server/netd.rc
index 4fc6fd8c..81006369 100644
--- a/server/netd.rc
+++ b/server/netd.rc
@@ -4,3 +4,5 @@ service netd /system/bin/netd
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet
+ onrestart restart zygote
+ onrestart restart zygote_secondary
diff --git a/tests/Android.mk b/tests/Android.mk
index a6fd308e..a2440ea3 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -49,7 +49,9 @@ LOCAL_SRC_FILES := binder_test.cpp \
../server/dns/DnsTlsServer.cpp \
../server/dns/DnsTlsSessionCache.cpp \
../server/dns/DnsTlsSocket.cpp \
-
+ ../server/InterfaceController.cpp \
+ ../server/NetlinkCommands.cpp \
+ ../server/XfrmController.cpp
LOCAL_MODULE_TAGS := eng tests
include $(BUILD_NATIVE_TEST)
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 51314f52..0913aa5f 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -42,12 +42,15 @@
#include <logwrap/logwrap.h>
#include <netutils/ifc.h>
+#include "InterfaceController.h"
#include "NetdConstants.h"
#include "Stopwatch.h"
+#include "XfrmController.h"
#include "tun_interface.h"
#include "android/net/INetd.h"
#include "android/net/UidRange.h"
#include "binder/IServiceManager.h"
+#include "netdutils/Syscalls.h"
#define IP_PATH "/system/bin/ip"
#define IP6TABLES_PATH "/system/bin/ip6tables"
@@ -61,6 +64,8 @@ using android::base::StartsWith;
using android::net::INetd;
using android::net::TunInterface;
using android::net::UidRange;
+using android::net::XfrmController;
+using android::netdutils::sSyscalls;
using android::os::PersistableBundle;
static const char* IP_RULE_V4 = "-4";
@@ -92,6 +97,8 @@ public:
mNetd->networkDestroy(TEST_NETID2);
}
+ bool allocateIpSecResources(bool expectOk, int32_t *spi);
+
// Static because setting up the tun interface takes about 40ms.
static void SetUpTestCase() {
ASSERT_EQ(0, sTun.init());
@@ -252,18 +259,18 @@ TEST_F(BinderTest, TestVirtualTunnelInterface) {
int32_t iKey;
int32_t oKey;
} kTestData[] = {
- { "IPV4", "test_vti", "127.0.0.1", "8.8.8.8", 0x1234 + 53, 0x1234 + 53 },
- { "IPV6", "test_vti6", "::1", "2001:4860:4860::8888", 0x1234 + 50, 0x1234 + 50 },
+ {"IPV4", "test_vti", "127.0.0.1", "8.8.8.8", 0x1234 + 53, 0x1234 + 53},
+ {"IPV6", "test_vti6", "::1", "2001:4860:4860::8888", 0x1234 + 50, 0x1234 + 50},
};
for (unsigned int i = 0; i < arraysize(kTestData); i++) {
- const auto &td = kTestData[i];
+ const auto& td = kTestData[i];
binder::Status status;
// Create Virtual Tunnel Interface.
- status = mNetd->addVirtualTunnelInterface(td.deviceName, td.localAddress,
- td.remoteAddress, td.iKey, td.oKey);
+ status = mNetd->addVirtualTunnelInterface(td.deviceName, td.localAddress, td.remoteAddress,
+ td.iKey, td.oKey);
EXPECT_TRUE(status.isOk()) << td.family << status.exceptionMessage();
// Update Virtual Tunnel Interface.
@@ -277,6 +284,58 @@ TEST_F(BinderTest, TestVirtualTunnelInterface) {
}
}
+#define RETURN_FALSE_IF_NEQ(_expect_, _ret_) \
+ do { if ((_expect_) != (_ret_)) return false; } while(false)
+bool BinderTest::allocateIpSecResources(bool expectOk, int32_t *spi) {
+ netdutils::Status status = XfrmController::ipSecAllocateSpi(0, "::", "::1", 123, spi);
+ SCOPED_TRACE(status);
+ RETURN_FALSE_IF_NEQ(status.ok(), expectOk);
+
+ // Add a policy
+ status = XfrmController::ipSecAddSecurityPolicy(0, 0, "::", "::1", 123, 0, 0);
+ SCOPED_TRACE(status);
+ RETURN_FALSE_IF_NEQ(status.ok(), expectOk);
+
+ // Add an ipsec interface
+ status = netdutils::statusFromErrno(
+ XfrmController::addVirtualTunnelInterface(
+ "ipsec_test", "::", "::1", 0xF00D, 0xD00D, false),
+ "addVirtualTunnelInterface");
+ return (status.ok() == expectOk);
+}
+
+
+TEST_F(BinderTest, TestXfrmControllerInit) {
+ netdutils::Status status;
+ status = XfrmController::Init();
+ SCOPED_TRACE(status);
+ ASSERT_TRUE(status.ok());
+
+ int32_t spi = 0;
+
+ ASSERT_TRUE(allocateIpSecResources(true, &spi));
+ ASSERT_TRUE(allocateIpSecResources(false, &spi));
+
+ status = XfrmController::Init();
+ ASSERT_TRUE(allocateIpSecResources(true, &spi));
+
+ // Clean up
+ status = XfrmController::ipSecDeleteSecurityAssociation(0, "::", "::1", 123, spi, 0);
+ SCOPED_TRACE(status);
+ ASSERT_TRUE(status.ok());
+
+ status = XfrmController::ipSecDeleteSecurityPolicy(0, 0, "::", "::1", 0, 0);
+ SCOPED_TRACE(status);
+ ASSERT_TRUE(status.ok());
+
+ // Remove Virtual Tunnel Interface.
+ status = netdutils::statusFromErrno(
+ XfrmController::removeVirtualTunnelInterface("ipsec_test"),
+ "removeVirtualTunnelInterface");
+
+ ASSERT_TRUE(status.ok());
+}
+
static int bandwidthDataSaverEnabled(const char *binary) {
std::vector<std::string> lines = listIptablesRule(binary, "bw_data_saver");