Adding XFRM mark support for xfrm global policy
The xfrm mark will be sent to kernel in XFRMA_MARK netlink
attribute.
Bug: 63589600
Test: runtest -x server/netd_unit_test.cpp
Change-Id: If2d2fdda2d0b3959ed79a3b948b033d76e4236aa
diff --git a/server/XfrmControllerTest.cpp b/server/XfrmControllerTest.cpp
index 762bede..46ef6e4 100644
--- a/server/XfrmControllerTest.cpp
+++ b/server/XfrmControllerTest.cpp
@@ -102,6 +102,8 @@
static constexpr int DROID_SPI = 0xD1201D;
static constexpr size_t KEY_LENGTH = 32;
static constexpr int NLMSG_DEFAULTSIZE = 8192;
+static constexpr uint32_t TEST_XFRM_MARK = 0x123;
+static constexpr uint32_t TEST_XFRM_MASK = 0xFFFFFFFF;
static constexpr char LOCALHOST_V4[] = "127.0.0.1";
static constexpr char LOCALHOST_V6[] = "::1";
@@ -277,7 +279,8 @@
size_t expectedMsgLength =
NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_info)) +
NLA_ALIGN(offsetof(XfrmController::nlattr_algo_crypt, key) + KEY_LENGTH) +
- NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH);
+ NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH) +
+ NLA_ALIGN(sizeof(XfrmController::nlattr_xfrm_mark));
std::vector<uint8_t> nlMsgBuf;
EXPECT_CALL(mockSyscalls, writev(_, _))
@@ -288,10 +291,10 @@
XfrmController ctrl;
Status res = ctrl.ipSecAddSecurityAssociation(
1 /* resourceId */, static_cast<int>(mode), localAddr, remoteAddr,
- 0 /* underlying network */, DROID_SPI, "hmac(sha256)" /* auth algo */,
- authKey, 128 /* auth trunc length */, "cbc(aes)" /* encryption algo */, cryptKey,
- 0 /* crypt trunc length? */, "" /* AEAD algo */, {}, 0,
- static_cast<int>(XfrmEncapType::NONE), 0 /* local port */, 0 /* remote port */);
+ 0 /* underlying network */, DROID_SPI, TEST_XFRM_MARK /* mark */, TEST_XFRM_MASK /* mask */,
+ "hmac(sha256)" /* auth algo */, authKey, 128 /* auth trunc length */,
+ "cbc(aes)" /* encryption algo */, cryptKey, 0 /* crypt trunc length? */, "" /* AEAD algo */,
+ {}, 0, static_cast<int>(XfrmEncapType::NONE), 0 /* local port */, 0 /* remote port */);
EXPECT_TRUE(isOk(res)) << res;
EXPECT_EQ(expectedMsgLength, nlMsgBuf.size());
@@ -324,7 +327,9 @@
// Extract and check the encryption/authentication algorithm
XfrmController::nlattr_algo_crypt encryptAlgo{};
XfrmController::nlattr_algo_auth authAlgo{};
- auto attrHandler = [&encryptAlgo, &authAlgo](const nlattr& attr, const Slice& attr_payload) {
+ XfrmController::nlattr_xfrm_mark mark{};
+ auto attrHandler = [&encryptAlgo, &authAlgo, &mark](const nlattr& attr,
+ const Slice& attr_payload) {
Slice buf = attr_payload;
if (attr.nla_type == XFRMA_ALG_CRYPT) {
encryptAlgo.hdr = attr;
@@ -336,6 +341,9 @@
netdutils::extract(buf, authAlgo.auth);
buf = drop(buf, sizeof(xfrm_algo_auth));
netdutils::extract(buf, authAlgo.key);
+ } else if (attr.nla_type == XFRMA_MARK) {
+ mark.hdr = attr;
+ netdutils::extract(buf, mark.mark);
} else {
FAIL() << "Unexpected nlattr type: " << attr.nla_type;
}
@@ -347,6 +355,8 @@
reinterpret_cast<void*>(&encryptAlgo.key), KEY_LENGTH));
EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(authKey.data()),
reinterpret_cast<void*>(&authAlgo.key), KEY_LENGTH));
+ EXPECT_EQ(TEST_XFRM_MARK, mark.mark.v);
+ EXPECT_EQ(TEST_XFRM_MASK, mark.mark.m);
}
TEST_P(XfrmControllerParameterizedTest, TestTransportModeIpSecAddSecurityAssociation) {
@@ -371,7 +381,7 @@
XfrmController ctrl;
Status res = ctrl.ipSecAddSecurityAssociation(
1, static_cast<int>(XfrmMode::TRANSPORT),
- LOCALHOST_V6, TEST_ADDR_V6, 0, DROID_SPI, "hmac(sha256)", {}, 128, "cbc(aes)",
+ LOCALHOST_V6, TEST_ADDR_V6, 0, DROID_SPI, 0, 0, "hmac(sha256)", {}, 128, "cbc(aes)",
{}, 0, "", {}, 0, static_cast<int>(XfrmEncapType::ESPINUDP_NON_IKE), 0, 0);
EXPECT_FALSE(isOk(res)) << "IPv6 UDP encap not rejected";
@@ -471,10 +481,11 @@
const std::string remoteAddr = (version == 6) ? TEST_ADDR_V6 : TEST_ADDR_V4;
NetlinkResponse response{};
- response.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
+ response.hdr.nlmsg_type = XFRM_MSG_DELSA;
Slice responseSlice = netdutils::makeSlice(response);
- size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_id));
+ size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_id)) +
+ NLA_ALIGN(sizeof(XfrmController::nlattr_xfrm_mark));
std::vector<uint8_t> nlMsgBuf;
EXPECT_CALL(mockSyscalls, writev(_, _))
@@ -483,8 +494,8 @@
.WillOnce(DoAll(SetArgSlice<1>(responseSlice), Return(responseSlice)));
XfrmController ctrl;
- Status res = ctrl.ipSecDeleteSecurityAssociation(
- 1 /* resourceId */, localAddr, remoteAddr, DROID_SPI);
+ Status res = ctrl.ipSecDeleteSecurityAssociation(1 /* resourceId */, localAddr, remoteAddr,
+ DROID_SPI, TEST_XFRM_MARK, TEST_XFRM_MASK);
EXPECT_TRUE(isOk(res)) << res;
EXPECT_EQ(expectedMsgLength, nlMsgBuf.size());
@@ -510,7 +521,8 @@
Slice responseSlice = netdutils::makeSlice(response);
size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userpolicy_info)) +
- NLMSG_ALIGN(sizeof(XfrmController::nlattr_user_tmpl));
+ NLMSG_ALIGN(sizeof(XfrmController::nlattr_user_tmpl)) +
+ NLMSG_ALIGN(sizeof(XfrmController::nlattr_xfrm_mark));
std::vector<uint8_t> nlMsgBuf;
EXPECT_CALL(mockSyscalls, writev(_, _))
@@ -519,9 +531,9 @@
.WillOnce(DoAll(SetArgSlice<1>(responseSlice), Return(responseSlice)));
XfrmController ctrl;
- Status res =
- ctrl.ipSecAddSecurityPolicy(1 /* resourceId */, static_cast<int>(XfrmDirection::OUT),
- localAddr, remoteAddr, 0 /* SPI */);
+ Status res = ctrl.ipSecAddSecurityPolicy(
+ 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), localAddr, remoteAddr,
+ 0 /* SPI */, TEST_XFRM_MARK, TEST_XFRM_MASK);
EXPECT_TRUE(isOk(res)) << res;
EXPECT_EQ(expectedMsgLength, nlMsgBuf.size());
@@ -540,13 +552,17 @@
// Drop the user policy info.
Slice attr_buf = drop(nlMsgSlice, NLA_ALIGN(sizeof(xfrm_userpolicy_info)));
- // Extract and check the user tmpl.
+ // Extract and check the user tmpl and mark.
XfrmController::nlattr_user_tmpl usertmpl{};
- auto attrHandler = [&usertmpl](const nlattr& attr, const Slice& attr_payload) {
+ XfrmController::nlattr_xfrm_mark mark{};
+ auto attrHandler = [&usertmpl, &mark](const nlattr& attr, const Slice& attr_payload) {
Slice buf = attr_payload;
if (attr.nla_type == XFRMA_TMPL) {
usertmpl.hdr = attr;
netdutils::extract(buf, usertmpl.tmpl);
+ } else if (attr.nla_type == XFRMA_MARK) {
+ mark.hdr = attr;
+ netdutils::extract(buf, mark.mark);
} else {
FAIL() << "Unexpected nlattr type: " << attr.nla_type;
}
@@ -554,6 +570,9 @@
forEachNetlinkAttribute(attr_buf, attrHandler);
expectAddressEquals(family, remoteAddr, usertmpl.tmpl.id.daddr);
+ EXPECT_EQ(TEST_XFRM_MARK, mark.mark.v);
+ EXPECT_EQ(TEST_XFRM_MASK, mark.mark.m);
+
}
TEST_P(XfrmControllerParameterizedTest, TestIpSecUpdateSecurityPolicy) {
@@ -566,7 +585,8 @@
Slice responseSlice = netdutils::makeSlice(response);
size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userpolicy_info)) +
- NLMSG_ALIGN(sizeof(XfrmController::nlattr_user_tmpl));
+ NLMSG_ALIGN(sizeof(XfrmController::nlattr_user_tmpl)) +
+ NLMSG_ALIGN(sizeof(XfrmController::nlattr_xfrm_mark));
std::vector<uint8_t> nlMsgBuf;
EXPECT_CALL(mockSyscalls, writev(_, _))
@@ -575,9 +595,9 @@
.WillOnce(DoAll(SetArgSlice<1>(responseSlice), Return(responseSlice)));
XfrmController ctrl;
- Status res =
- ctrl.ipSecUpdateSecurityPolicy(1 /* resourceId */, static_cast<int>(XfrmDirection::OUT),
- localAddr, remoteAddr, 0 /* SPI */);
+ Status res = ctrl.ipSecUpdateSecurityPolicy(
+ 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), localAddr, remoteAddr,
+ 0 /* SPI */, 0 /* Mark */, 0 /* Mask */);
EXPECT_TRUE(isOk(res)) << res;
EXPECT_EQ(expectedMsgLength, nlMsgBuf.size());
@@ -597,7 +617,8 @@
response.hdr.nlmsg_type = XFRM_MSG_DELPOLICY;
Slice responseSlice = netdutils::makeSlice(response);
- size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userpolicy_id));
+ size_t expectedMsgLength = NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_userpolicy_id)) +
+ NLMSG_ALIGN(sizeof(XfrmController::nlattr_xfrm_mark));
std::vector<uint8_t> nlMsgBuf;
EXPECT_CALL(mockSyscalls, writev(_, _))
@@ -606,9 +627,9 @@
.WillOnce(DoAll(SetArgSlice<1>(responseSlice), Return(responseSlice)));
XfrmController ctrl;
- Status res =
- ctrl.ipSecDeleteSecurityPolicy(1 /* resourceId */, static_cast<int>(XfrmDirection::OUT),
- localAddr, remoteAddr);
+ Status res = ctrl.ipSecDeleteSecurityPolicy(
+ 1 /* resourceId */, static_cast<int>(XfrmDirection::OUT), localAddr, remoteAddr,
+ TEST_XFRM_MARK, TEST_XFRM_MASK);
EXPECT_TRUE(isOk(res)) << res;
EXPECT_EQ(expectedMsgLength, nlMsgBuf.size());
@@ -620,6 +641,15 @@
netdutils::extract(nlMsgSlice, policyid);
EXPECT_EQ(static_cast<uint8_t>(XfrmDirection::OUT), policyid.dir);
+
+ // Drop the user policy id.
+ nlMsgSlice = drop(nlMsgSlice, NLA_ALIGN(sizeof(xfrm_userpolicy_id)));
+ // Extract and check the mark.
+ XfrmController::nlattr_xfrm_mark mark{};
+ netdutils::extract(nlMsgSlice, mark);
+ EXPECT_EQ(TEST_XFRM_MARK, mark.mark.v);
+ EXPECT_EQ(TEST_XFRM_MASK, mark.mark.m);
+
}
} // namespace net