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/XfrmController.cpp b/server/XfrmController.cpp
index 92dd757..f34a33b 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -385,7 +385,7 @@
 
     XfrmSaInfo saInfo{};
     netdutils::Status ret =
-        fillXfrmId(sourceAddress, destinationAddress, INVALID_SPI, transformId, &saInfo);
+        fillXfrmId(sourceAddress, destinationAddress, INVALID_SPI, 0, 0, transformId, &saInfo);
     if (!isOk(ret)) {
         return ret;
     }
@@ -415,10 +415,11 @@
 netdutils::Status XfrmController::ipSecAddSecurityAssociation(
     int32_t transformId, int32_t mode, const std::string& sourceAddress,
     const std::string& destinationAddress, int64_t underlyingNetworkHandle, int32_t spi,
-    const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
-    const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
-    const std::string& aeadAlgo, const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits,
-    int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort) {
+    int32_t markValue, int32_t markMask, const std::string& authAlgo,
+    const std::vector<uint8_t>& authKey, int32_t authTruncBits, const std::string& cryptAlgo,
+    const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits, const std::string& aeadAlgo,
+    const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType,
+    int32_t encapLocalPort, int32_t encapRemotePort) {
     ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
     ALOGD("transformId=%d", transformId);
     ALOGD("mode=%d", mode);
@@ -426,6 +427,8 @@
     ALOGD("destinationAddress=%s", destinationAddress.c_str());
     ALOGD("underlyingNetworkHandle=%" PRIx64, underlyingNetworkHandle);
     ALOGD("spi=%0.8x", spi);
+    ALOGD("markValue=%x", markValue);
+    ALOGD("markMask=%x", markMask);
     ALOGD("authAlgo=%s", authAlgo.c_str());
     ALOGD("authTruncBits=%d", authTruncBits);
     ALOGD("cryptAlgo=%s", cryptAlgo.c_str());
@@ -437,8 +440,8 @@
     ALOGD("encapRemotePort=%d", encapRemotePort);
 
     XfrmSaInfo saInfo{};
-    netdutils::Status ret =
-        fillXfrmId(sourceAddress, destinationAddress, spi, transformId, &saInfo);
+    netdutils::Status ret = fillXfrmId(sourceAddress, destinationAddress, spi, markValue, markMask,
+                                       transformId, &saInfo);
     if (!isOk(ret)) {
         return ret;
     }
@@ -494,18 +497,20 @@
     return ret;
 }
 
-netdutils::Status
-XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId,
-                                               const std::string& sourceAddress,
-                                               const std::string& destinationAddress, int32_t spi) {
+netdutils::Status XfrmController::ipSecDeleteSecurityAssociation(
+    int32_t transformId, const std::string& sourceAddress, const std::string& destinationAddress,
+    int32_t spi, int32_t markValue, int32_t markMask) {
     ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
     ALOGD("transformId=%d", transformId);
     ALOGD("sourceAddress=%s", sourceAddress.c_str());
     ALOGD("destinationAddress=%s", destinationAddress.c_str());
     ALOGD("spi=%0.8x", spi);
+    ALOGD("markValue=%x", markValue);
+    ALOGD("markMask=%x", markMask);
 
     XfrmId saId{};
-    netdutils::Status ret = fillXfrmId(sourceAddress, destinationAddress, spi, transformId, &saId);
+    netdutils::Status ret =
+        fillXfrmId(sourceAddress, destinationAddress, spi, markValue, markMask, transformId, &saId);
     if (!isOk(ret)) {
         return ret;
     }
@@ -527,10 +532,13 @@
 
 netdutils::Status XfrmController::fillXfrmId(const std::string& sourceAddress,
                                              const std::string& destinationAddress, int32_t spi,
+                                             int32_t markValue, int32_t markMask,
                                              int32_t transformId, XfrmId* xfrmId) {
     // Fill the straightforward fields first
     xfrmId->transformId = transformId;
     xfrmId->spi = htonl(spi);
+    xfrmId->mark.v = markValue;
+    xfrmId->mark.m = markMask;
 
     // Use the addresses to determine the address family and do validation
     xfrm_address_t sourceXfrmAddr{}, destXfrmAddr{};
@@ -575,7 +583,7 @@
 
     XfrmSaInfo saInfo{};
     netdutils::Status status =
-        fillXfrmId(sourceAddress, destinationAddress, spi, transformId, &saInfo);
+        fillXfrmId(sourceAddress, destinationAddress, spi, 0, 0, transformId, &saInfo);
     if (!isOk(status)) {
         ALOGE("Couldn't build SA ID %s", __FUNCTION__);
         return status;
@@ -658,36 +666,42 @@
 netdutils::Status XfrmController::ipSecAddSecurityPolicy(int32_t transformId, int32_t direction,
                                                          const std::string& localAddress,
                                                          const std::string& remoteAddress,
-                                                         int32_t spi) {
+                                                         int32_t spi, int32_t markValue,
+                                                         int32_t markMask) {
     return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, spi,
-                                 XFRM_MSG_NEWPOLICY);
+                                 markValue, markMask, XFRM_MSG_NEWPOLICY);
 }
 
 netdutils::Status XfrmController::ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction,
                                                             const std::string& localAddress,
                                                             const std::string& remoteAddress,
-                                                            int32_t spi) {
+                                                            int32_t spi, int32_t markValue,
+                                                            int32_t markMask) {
     return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, spi,
-                                 XFRM_MSG_UPDPOLICY);
+                                 markValue, markMask, XFRM_MSG_UPDPOLICY);
 }
 
 netdutils::Status XfrmController::ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction,
                                                             const std::string& localAddress,
-                                                            const std::string& remoteAddress) {
+                                                            const std::string& remoteAddress,
+                                                            int32_t markValue, int32_t markMask) {
     return processSecurityPolicy(transformId, direction, localAddress, remoteAddress, 0,
-                                 XFRM_MSG_DELPOLICY);
+                                 markValue, markMask, XFRM_MSG_DELPOLICY);
 }
 
 netdutils::Status XfrmController::processSecurityPolicy(int32_t transformId, int32_t direction,
                                                         const std::string& localAddress,
                                                         const std::string& remoteAddress,
-                                                        int32_t spi, int32_t msgType) {
+                                                        int32_t spi, int32_t markValue,
+                                                        int32_t markMask, int32_t msgType) {
     ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
     ALOGD("transformId=%d", transformId);
     ALOGD("direction=%d", direction);
     ALOGD("localAddress=%s", localAddress.c_str());
     ALOGD("remoteAddress=%s", remoteAddress.c_str());
     ALOGD("spi=%0.8x", spi);
+    ALOGD("markValue=%d", markValue);
+    ALOGD("markMask=%d", markMask);
     ALOGD("msgType=%d", msgType);
 
     XfrmSaInfo saInfo{};
@@ -696,7 +710,8 @@
     XfrmSocketImpl sock;
     RETURN_IF_NOT_OK(sock.open());
 
-    RETURN_IF_NOT_OK(fillXfrmId(localAddress, remoteAddress, spi, transformId, &saInfo));
+    RETURN_IF_NOT_OK(
+        fillXfrmId(localAddress, remoteAddress, spi, markValue, markMask, transformId, &saInfo));
 
     if (msgType == XFRM_MSG_DELPOLICY) {
         return deleteTunnelModeSecurityPolicy(saInfo, sock, static_cast<XfrmDirection>(direction));
@@ -719,6 +734,7 @@
     nlattr_algo_crypt crypt{};
     nlattr_algo_auth auth{};
     nlattr_algo_aead aead{};
+    nlattr_xfrm_mark xfrmmark{};
     nlattr_encap_tmpl encap{};
 
     enum {
@@ -731,8 +747,10 @@
         AUTH_PAD,
         AEAD,
         AEAD_PAD,
+        MARK,
+        MARK_PAD,
         ENCAP,
-        ENCAP_PAD
+        ENCAP_PAD,
     };
 
     std::vector<iovec> iov = {
@@ -745,6 +763,8 @@
         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
         {&aead, 0},     // adjust size if aead algo is present
         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+        {&xfrmmark, 0},   // adjust size if xfrm mark is present
+        {kPadBytes, 0},   // up to NLATTR_ALIGNTO pad bytes
         {&encap, 0},    // adjust size if encapsulating
         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
     };
@@ -773,8 +793,12 @@
     len = iov[AEAD].iov_len = fillNlAttrXfrmAlgoAead(record.aead, &aead);
     iov[AEAD_PAD].iov_len = NLA_ALIGN(len) - len;
 
+    len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
+    iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
+
     len = iov[ENCAP].iov_len = fillNlAttrXfrmEncapTmpl(record, &encap);
     iov[ENCAP_PAD].iov_len = NLA_ALIGN(len) - len;
+
     return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, &iov);
 }
 
@@ -885,19 +909,25 @@
 netdutils::Status XfrmController::deleteSecurityAssociation(const XfrmId& record,
                                                             const XfrmSocket& sock) {
     xfrm_usersa_id said{};
+    nlattr_xfrm_mark xfrmmark{};
 
-    enum { NLMSG_HDR, USERSAID, USERSAID_PAD };
+    enum { NLMSG_HDR, USERSAID, USERSAID_PAD, MARK, MARK_PAD };
 
     std::vector<iovec> iov = {
         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
         {&said, 0},     // main usersa_info struct
         {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
+        {&xfrmmark, 0},  // adjust size if xfrm mark is present
+        {kPadBytes, 0},  // up to NLATTR_ALIGNTO pad bytes
     };
 
     int len;
     len = iov[USERSAID].iov_len = fillUserSaId(record, &said);
     iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
 
+    len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
+    iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
+
     return sock.sendMessage(XFRM_MSG_DELSA, NETLINK_REQUEST_FLAGS, 0, &iov);
 }
 
@@ -955,6 +985,7 @@
                                                                  uint16_t msgType) {
     xfrm_userpolicy_info userpolicy{};
     nlattr_user_tmpl usertmpl{};
+    nlattr_xfrm_mark xfrmmark{};
 
     enum {
         NLMSG_HDR,
@@ -962,6 +993,8 @@
         USERPOLICY_PAD,
         USERTMPL,
         USERTMPL_PAD,
+        MARK,
+        MARK_PAD,
     };
 
     std::vector<iovec> iov = {
@@ -970,6 +1003,8 @@
         {kPadBytes, 0},   // up to NLMSG_ALIGNTO pad bytes of padding
         {&usertmpl, 0},   // adjust size if xfrm_user_tmpl struct is present
         {kPadBytes, 0},   // up to NLATTR_ALIGNTO pad bytes
+        {&xfrmmark, 0},   // adjust size if xfrm mark is present
+        {kPadBytes, 0},   // up to NLATTR_ALIGNTO pad bytes
     };
 
     int len;
@@ -979,6 +1014,9 @@
     len = iov[USERTMPL].iov_len = fillNlAttrUserTemplate(record, &usertmpl);
     iov[USERTMPL_PAD].iov_len = NLA_ALIGN(len) - len;
 
+    len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
+    iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
+
     return sock.sendMessage(msgType, NETLINK_REQUEST_FLAGS, 0, &iov);
 }
 
@@ -986,22 +1024,30 @@
                                                                  const XfrmSocket& sock,
                                                                  XfrmDirection direction) {
     xfrm_userpolicy_id policyid{};
+    nlattr_xfrm_mark xfrmmark{};
 
     enum {
         NLMSG_HDR,
         USERPOLICYID,
         USERPOLICYID_PAD,
+        MARK,
+        MARK_PAD,
     };
 
     std::vector<iovec> iov = {
         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
         {&policyid, 0}, // main xfrm_userpolicy_id struct
         {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
+        {&xfrmmark, 0},   // adjust size if xfrm mark is present
+        {kPadBytes, 0},   // up to NLATTR_ALIGNTO pad bytes
     };
 
     int len = iov[USERPOLICYID].iov_len = fillUserPolicyId(record, direction, &policyid);
     iov[USERPOLICYID_PAD].iov_len = NLMSG_ALIGN(len) - len;
 
+    len = iov[MARK].iov_len = fillNlAttrXfrmMark(record, &xfrmmark);
+    iov[MARK_PAD].iov_len = NLA_ALIGN(len) - len;
+
     return sock.sendMessage(XFRM_MSG_DELPOLICY, NETLINK_REQUEST_FLAGS, 0, &iov);
 }
 
@@ -1047,6 +1093,14 @@
     return len;
 }
 
+int XfrmController::fillNlAttrXfrmMark(const XfrmId& record, nlattr_xfrm_mark* mark) {
+    mark->mark.v = record.mark.v; // set to 0 if it's not used
+    mark->mark.m = record.mark.m; // set to 0 if it's not used
+    int len = NLA_HDRLEN + sizeof(xfrm_mark);
+    fillXfrmNlaHdr(&mark->hdr, XFRMA_MARK, len);
+    return len;
+}
+
 int XfrmController::fillUserPolicyId(const XfrmSaInfo& record, XfrmDirection direction,
                                      xfrm_userpolicy_id* usersp) {
     // For DELPOLICY, when index is absent, selector is needed to match the policy