netd: Use a persistent iptables[6]-restore process

iptables-restore and ip[6]tables-restore are forked on demand
whenever we need them, and their stdin/out/err are replaced by
pipes to the parent process. All commands are sent via the stdin
pipe. We also add SIGCHLD handling so that we can detect error
conditions and restart the process whenever required.

Bug: 32323979
Test: Manual
Test: netd_unit_test, netd_integration_test

Change-Id: Ia12ee01f8b45e5b8a699c27eea1b6b55d40f16b5
diff --git a/server/NetdConstants.cpp b/server/NetdConstants.cpp
index 7bd4316..f8a0d36 100644
--- a/server/NetdConstants.cpp
+++ b/server/NetdConstants.cpp
@@ -29,13 +29,13 @@
 #include <cutils/log.h>
 #include <logwrap/logwrap.h>
 
+#include "Controllers.h"
 #include "NetdConstants.h"
+#include "IptablesRestoreController.h"
 
 const char * const OEM_SCRIPT_PATH = "/system/bin/oem-iptables-init.sh";
 const char * const IPTABLES_PATH = "/system/bin/iptables";
 const char * const IP6TABLES_PATH = "/system/bin/ip6tables";
-const char * const IPTABLES_RESTORE_PATH = "/system/bin/iptables-restore";
-const char * const IP6TABLES_RESTORE_PATH = "/system/bin/ip6tables-restore";
 const char * const TC_PATH = "/system/bin/tc";
 const char * const IP_PATH = "/system/bin/ip";
 const char * const ADD = "add";
@@ -119,41 +119,8 @@
     return res;
 }
 
-static int execIptablesRestoreCommand(const char *cmd, const std::string& commands) {
-    const char *argv[] = {
-        cmd,
-        "--noflush",  // Don't flush the whole table.
-        "-w",         // Wait instead of failing if the lock is held.
-    };
-    AndroidForkExecvpOption opt[1] = {
-        {
-            .opt_type = FORK_EXECVP_OPTION_INPUT,
-            .opt_input.input = reinterpret_cast<const uint8_t*>(commands.c_str()),
-            .opt_input.input_len = commands.size(),
-        }
-    };
-
-    int status = 0;
-    int res = android_fork_execvp_ext(
-            ARRAY_SIZE(argv), (char**)argv, &status, false /* ignore_int_quit */, LOG_NONE,
-            false /* abbreviated */, NULL /* file_path */, opt, ARRAY_SIZE(opt));
-    if (res || status) {
-        ALOGE("%s failed with res=%d, status=%d", argv[0], res, status);
-        return -1;
-    }
-
-    return 0;
-}
-
 int execIptablesRestore(IptablesTarget target, const std::string& commands) {
-    int res = 0;
-    if (target == V4 || target == V4V6) {
-        res |= execIptablesRestoreCommand(IPTABLES_RESTORE_PATH, commands);
-    }
-    if (target == V6 || target == V4V6) {
-        res |= execIptablesRestoreCommand(IP6TABLES_RESTORE_PATH, commands);
-    }
-    return res;
+    return android::net::gCtls->iptablesRestoreCtrl.execute(target, commands);
 }
 
 /*