[ipsec-doze] Add fchown capabilities, and fw rules

Add some firewall rules to allow doze mode packets to be sent/received
on ESP & no-socket packets. No-socket packets are no security risk
because they are either forwarded, going to be forwarded, or will be
dropped at routing tables (unless they are ESP).

Bug: 62994731
Test: New tests added, run
Change-Id: I2d8704498b564403d94123e4938091dee8fb98c1
diff --git a/libnetdutils/Syscalls.cpp b/libnetdutils/Syscalls.cpp
index 5354341..9a05e3b 100644
--- a/libnetdutils/Syscalls.cpp
+++ b/libnetdutils/Syscalls.cpp
@@ -65,6 +65,15 @@
         return status::ok;
     }
 
+    Status getsockopt(Fd sock, int level, int optname, void* optval,
+                      socklen_t* optlen) const override {
+        auto rv = ::getsockopt(sock.get(), level, optname, optval, optlen);
+        if (rv == -1) {
+            return statusFromErrno(errno, "getsockopt() failed");
+        }
+        return status::ok;
+    }
+
     Status setsockopt(Fd sock, int level, int optname, const void* optval,
                       socklen_t optlen) const override {
         auto rv = ::setsockopt(sock.get(), level, optname, optval, optlen);
diff --git a/libnetdutils/SyscallsTest.cpp b/libnetdutils/SyscallsTest.cpp
index a754d1c..da93b76 100644
--- a/libnetdutils/SyscallsTest.cpp
+++ b/libnetdutils/SyscallsTest.cpp
@@ -108,6 +108,26 @@
     EXPECT_EQ(kError, sys.setsockopt(kFd, kLevel, kOptname, expected));
 }
 
+TEST_F(SyscallsTest, getsockopt) {
+    constexpr Fd kFd(40);
+    constexpr int kLevel = 50;
+    constexpr int kOptname = 70;
+    sockaddr_nl expected = {};
+    socklen_t optLen = 0;
+    auto& sys = sSyscalls.get();
+
+    // Success
+    EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
+        .WillOnce(Return(status::ok));
+    EXPECT_EQ(status::ok, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
+
+    // Failure
+    const Status kError = statusFromErrno(EINVAL, "test");
+    EXPECT_CALL(mSyscalls, getsockopt(kFd, kLevel, kOptname, &expected, &optLen))
+        .WillOnce(Return(kError));
+    EXPECT_EQ(kError, sys.getsockopt(kFd, kLevel, kOptname, &expected, &optLen));
+}
+
 TEST_F(SyscallsTest, bind) {
     constexpr Fd kFd(40);
     sockaddr_nl expected = {};
diff --git a/libnetdutils/include/netdutils/MockSyscalls.h b/libnetdutils/include/netdutils/MockSyscalls.h
index 149ba59..06ca859 100644
--- a/libnetdutils/include/netdutils/MockSyscalls.h
+++ b/libnetdutils/include/netdutils/MockSyscalls.h
@@ -37,6 +37,8 @@
                        StatusOr<UniqueFd>(const std::string& pathname, int flags, mode_t mode));
     MOCK_CONST_METHOD3(socket, StatusOr<UniqueFd>(int domain, int type, int protocol));
     MOCK_CONST_METHOD3(getsockname, Status(Fd sock, sockaddr* addr, socklen_t* addrlen));
+    MOCK_CONST_METHOD5(getsockopt, Status(Fd sock, int level, int optname, void* optval,
+                                          socklen_t *optlen));
     MOCK_CONST_METHOD5(setsockopt, Status(Fd sock, int level, int optname, const void* optval,
                                           socklen_t optlen));
 
diff --git a/libnetdutils/include/netdutils/Syscalls.h b/libnetdutils/include/netdutils/Syscalls.h
index 0e336b6..4c9a004 100644
--- a/libnetdutils/include/netdutils/Syscalls.h
+++ b/libnetdutils/include/netdutils/Syscalls.h
@@ -47,6 +47,9 @@
 
     virtual Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const = 0;
 
+    virtual Status getsockopt(Fd sock, int level, int optname, void *optval,
+                              socklen_t *optlen) const = 0;
+
     virtual Status setsockopt(Fd sock, int level, int optname, const void* optval,
                               socklen_t optlen) const = 0;
 
@@ -115,6 +118,11 @@
     }
 
     template <typename SockoptT>
+    Status getsockopt(Fd sock, int level, int optname, void* optval, socklen_t* optlen) const {
+        return getsockopt(sock, level, optname, optval, optlen);
+    }
+
+    template <typename SockoptT>
     Status setsockopt(Fd sock, int level, int optname, const SockoptT& opt) const {
         return setsockopt(sock, level, optname, &opt, sizeof(opt));
     }