Add UDP Encap Support to XfrmController

-Add xfrm_encap_tmpl to ADDSA

Bug: 34812052
Test: cts - IpSecManagerTest:testUdpEncapsulation()

Change-Id: I743a2dbe4f5a497b2f77f7713a68e8970adfb7de
diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp
index f1e0e23..344b268 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -25,6 +25,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#define __STDC_FORMAT_MACROS
 #include <inttypes.h>
 
 #include <arpa/inet.h>
@@ -107,10 +109,14 @@
 void* kPadBytes = static_cast<void*>(kPadBytesArray);
 
 #if VDBG
-#define LOG_HEX(__desc16__, __buf__, __len__) \
-    do{ logHex(__desc16__, __buf__, __len__); }while(0)
-#define LOG_IOV(__iov__, __iov_len__) \
-    do{ logIov(__iov__, __iov_len__); }while(0)
+#define LOG_HEX(__desc16__, __buf__, __len__)                                                      \
+    do {                                                                                           \
+        logHex(__desc16__, __buf__, __len__);                                                      \
+    } while (0)
+#define LOG_IOV(__iov__, __iov_len__)                                                              \
+    do {                                                                                           \
+        logIov(__iov__, __iov_len__);                                                              \
+    } while (0)
 
 void logHex(const char* desc16, const char* buf, size_t len) {
     char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
@@ -314,7 +320,6 @@
                                      const std::string& localAddress,
                                      const std::string& remoteAddress, int32_t inSpi,
                                      int32_t* outSpi) {
-
     ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
     ALOGD("transformId=%d", transformId);
     ALOGD("direction=%d", direction);
@@ -351,7 +356,7 @@
 
 int XfrmController::ipSecAddSecurityAssociation(
     int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
-    const std::string& remoteAddress, int64_t /* underlyingNetworkHandle */, int32_t spi,
+    const std::string& remoteAddress, 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,
     int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort, int32_t* allocatedSpi) {
@@ -363,6 +368,7 @@
     ALOGD("direction=%d", direction);
     ALOGD("localAddress=%s", localAddress.c_str());
     ALOGD("remoteAddress=%s", remoteAddress.c_str());
+    ALOGD("underlyingNetworkHandle=%" PRIx64, underlyingNetworkHandle);
     ALOGD("spi=%0.8x", spi);
     ALOGD("authAlgo=%s", authAlgo.c_str());
     ALOGD("authTruncBits=%d", authTruncBits);
@@ -406,6 +412,32 @@
                    // failed to open
     }
 
+    switch (static_cast<XfrmEncapType>(encapType)) {
+        case XfrmEncapType::ESPINUDP:
+        case XfrmEncapType::ESPINUDP_NON_IKE:
+            if (saInfo.addrFamily != AF_INET) {
+                return -EAFNOSUPPORT;
+            }
+            switch (saInfo.direction) {
+                case XfrmDirection::IN:
+                    saInfo.encap.srcPort = encapRemotePort;
+                    saInfo.encap.dstPort = encapLocalPort;
+                    break;
+                case XfrmDirection::OUT:
+                    saInfo.encap.srcPort = encapLocalPort;
+                    saInfo.encap.dstPort = encapRemotePort;
+                    break;
+                default:
+                    return -EINVAL;
+            }
+        // fall through
+        case XfrmEncapType::NONE:
+            saInfo.encap.type = static_cast<XfrmEncapType>(encapType);
+            break;
+        default:
+            return -EINVAL;
+    }
+
     ret = createTransportModeSecurityAssociation(saInfo, sock);
     if (ret < 0) {
         ALOGD("Failed creating a Security Association, line=%d", __LINE__);
@@ -419,7 +451,6 @@
 int XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
                                                    const std::string& localAddress,
                                                    const std::string& remoteAddress, int32_t spi) {
-
     ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
     ALOGD("transformId=%d", transformId);
     ALOGD("direction=%d", direction);
@@ -526,8 +557,8 @@
 
     if (saInfo.addrFamily != saddr.ss_family) {
         ALOGE("Transform address family(%d) differs from socket address "
-                "family(%d)!",
-                saInfo.addrFamily, saddr.ss_family);
+              "family(%d)!",
+              saInfo.addrFamily, saddr.ss_family);
         return -EINVAL;
     }
 
@@ -581,8 +612,20 @@
     xfrm_usersa_info usersa{};
     nlattr_algo_crypt crypt{};
     nlattr_algo_auth auth{};
+    nlattr_encap_tmpl encap{};
 
-    enum { NLMSG_HDR, USERSA, USERSA_PAD, CRYPT, CRYPT_PAD, AUTH, AUTH_PAD, iovLen };
+    enum {
+        NLMSG_HDR,
+        USERSA,
+        USERSA_PAD,
+        CRYPT,
+        CRYPT_PAD,
+        AUTH,
+        AUTH_PAD,
+        ENCAP,
+        ENCAP_PAD,
+        iovLen
+    };
 
     iovec iov[] = {
         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
@@ -592,6 +635,8 @@
         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
         {&auth, 0},     // adjust size if auth algo is present
         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+        {&encap, 0},    // adjust size if auth algo is present
+        {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
     };
 
     int len;
@@ -604,6 +649,8 @@
     len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
     iov[AUTH_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, iovLen);
 }
 
@@ -632,6 +679,19 @@
     return len;
 }
 
+int XfrmController::fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl) {
+    if (record.encap.type == XfrmEncapType::NONE) {
+        return 0;
+    }
+
+    int len = NLA_HDRLEN + sizeof(xfrm_encap_tmpl);
+    tmpl->tmpl.encap_type = static_cast<uint16_t>(record.encap.type);
+    tmpl->tmpl.encap_sport = htons(record.encap.srcPort);
+    tmpl->tmpl.encap_dport = htons(record.encap.dstPort);
+    fillXfrmNlaHdr(&tmpl->hdr, XFRMA_ENCAP, len);
+    return len;
+}
+
 int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
     fillTransportModeSelector(record, &usersa->sel);
 
@@ -712,7 +772,7 @@
 
         if (ret == 0) {
             *outSpi = spi;
-            ALOGD("Allocated an SPI: %d", *outSpi);
+            ALOGD("Allocated an SPI: %x", *outSpi);
         } else {
             *outSpi = INVALID_SPI;
             ALOGE("SPI Allocation Failed with error %d", ret);
@@ -730,7 +790,8 @@
     fillTransportModeSelector(record, &usersp->sel);
     fillXfrmLifetimeDefaults(&usersp->lft);
     fillXfrmCurLifetimeDefaults(&usersp->curlft);
-    /* if (index) index & 0x3 == dir -- must be true xfrm_user.c:verify_newpolicy_info() */
+    /* if (index) index & 0x3 == dir -- must be true
+     * xfrm_user.c:verify_newpolicy_info() */
     usersp->index = 0;
     usersp->dir = static_cast<uint8_t>(record.direction);
     usersp->action = XFRM_POLICY_ALLOW;