Add Functions to flush SADB, Policy DB, and Ifaces

-Add ipSecFlushState() which flushes the kernel's
 SA DB and Policy DB.
-Add ipSecFlushInterfaces() which seeks and removes
 any interfaces that have the prefix 'ipsec'
-Automatically call these functions when netd restarts
-Make XfrmController's methods static
-Add integration tests to verify flushing of policy
 states, and interfaces
-Convert XfrmController functions to static for easier
 test-ability

Bug: 74560705
Test: runtest ...netd_integration_test.cpp
Change-Id: Id60e7c29ff9aeee7f5ccd505b86c94cce858745f
diff --git a/server/Controllers.cpp b/server/Controllers.cpp
index b0b1925..221a20a 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 @@
         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/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 29ed511..b348339 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -465,7 +465,6 @@
     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 744728a..adc02b7 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 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 @@
 //
 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 298fae6..f21dfa1 100644
--- a/server/XfrmController.h
+++ b/server/XfrmController.h
@@ -125,14 +125,16 @@
 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 @@
         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 @@
 
     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 @@
     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)
 };