netd: Idletimer vs Nat vs Bandwidth controllers

* modified iptables users to work in controller specific custom chains.
 - each controller only works withing his own custom chains and not the
  top level ones (INPUT, OUTPUT, FORWARD, POSTROUTING,...)
 - CommandListener now invokes setupIptablesHooks() for each controller
   once. That is the only time they are allowed to access the top-level
   chains.

* Added idletimer controller.
  From https://android-git.corp.google.com/g/#/c/180769/2
 - supported commands
   . ndc idletimer enable
   . ndc idletimer add <iface> <timeout>
   . ndc idletimer remove <iface> <timeout_used_during_add>
 There is a framework change elsewhere that receives netlink messages.

Signed-off-by: Ashish Sharma <ashishsharma@google.com>
Signed-off-by: JP Abgrall <jpa@google.com>
Change-Id: Ia57450c09166ce20f21d1e3b49047ef1e98f2a3d
diff --git a/NatController.cpp b/NatController.cpp
index b68e4bf..db96ed3 100644
--- a/NatController.cpp
+++ b/NatController.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+
 #include <stdlib.h>
 #include <errno.h>
 #include <sys/socket.h>
@@ -29,13 +31,14 @@
 
 #include "NatController.h"
 #include "SecondaryTableController.h"
-#include "oem_iptables_hook.h"
 #include "NetdConstants.h"
 
 extern "C" int system_nosh(const char *command);
 
 NatController::NatController(SecondaryTableController *ctrl) {
     secondaryTableCtrl = ctrl;
+
+    setupIptablesHooks();
     setDefaults();
 }
 
@@ -55,21 +58,43 @@
 
     asprintf(&buffer, "%s %s", path, cmd);
     res = system_nosh(buffer);
+    ALOGV("runCmd() buffer='%s' res=%d", buffer, res);
     free(buffer);
     return res;
 }
 
-int NatController::setDefaults() {
-
+int NatController::setupIptablesHooks() {
     if (runCmd(IPTABLES_PATH, "-P INPUT ACCEPT"))
         return -1;
     if (runCmd(IPTABLES_PATH, "-P OUTPUT ACCEPT"))
         return -1;
-    if (runCmd(IPTABLES_PATH, "-P FORWARD DROP"))
+    if (runCmd(IPTABLES_PATH, "-P FORWARD ACCEPT"))
         return -1;
-    if (runCmd(IPTABLES_PATH, "-F FORWARD"))
+
+    // Order is important!
+    // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist)
+    // -F to flush the chain (no-op if doesn't exist).
+    // -N to create the chain (no-op if already exist).
+
+    runCmd(IPTABLES_PATH, "-D FORWARD -j natctrl_FORWARD");
+    runCmd(IPTABLES_PATH, "-F natctrl_FORWARD");
+    runCmd(IPTABLES_PATH, "-N natctrl_FORWARD");
+    if (runCmd(IPTABLES_PATH, "-A FORWARD -j natctrl_FORWARD"))
         return -1;
-    if (runCmd(IPTABLES_PATH, "-t nat -F"))
+
+    runCmd(IPTABLES_PATH, "-t nat -D POSTROUTING -j natctrl_nat_POSTROUTING");
+    runCmd(IPTABLES_PATH, "-t nat -F natctrl_nat_POSTROUTING");
+    runCmd(IPTABLES_PATH, "-t nat -N natctrl_nat_POSTROUTING");
+    if (runCmd(IPTABLES_PATH, "-t nat -A POSTROUTING -j natctrl_nat_POSTROUTING"))
+        return -1;
+
+    return 0;
+}
+
+int NatController::setDefaults() {
+    if (runCmd(IPTABLES_PATH, "-F natctrl_FORWARD"))
+        return -1;
+    if (runCmd(IPTABLES_PATH, "-t nat -F natctrl_nat_POSTROUTING"))
         return -1;
 
     runCmd(IP_PATH, "rule flush");
@@ -82,7 +107,6 @@
 
     natCount = 0;
 
-    setupOemIptablesHook();
     return 0;
 }
 
@@ -138,10 +162,17 @@
         return -1;
     }
 
+    /* Always make sure the drop rule is at the end */
+    snprintf(cmd, sizeof(cmd), "-D natctrl_FORWARD -j DROP");
+    runCmd(IPTABLES_PATH, cmd);
+    snprintf(cmd, sizeof(cmd), "-A natctrl_FORWARD -j DROP");
+    runCmd(IPTABLES_PATH, cmd);
+
+
     natCount++;
     // add this if we are the first added nat
     if (natCount == 1) {
-        snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
+        snprintf(cmd, sizeof(cmd), "-t nat -A natctrl_nat_POSTROUTING -o %s -j MASQUERADE", extIface);
         if (runCmd(IPTABLES_PATH, cmd)) {
             ALOGE("Error seting postroute rule: %s", cmd);
             // unwind what's been done, but don't care about success - what more could we do?
@@ -162,7 +193,7 @@
     char cmd[255];
 
     snprintf(cmd, sizeof(cmd),
-             "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
+             "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
              (add ? "A" : "D"),
              extIface, intIface);
     if (runCmd(IPTABLES_PATH, cmd) && add) {
@@ -170,36 +201,41 @@
     }
 
     snprintf(cmd, sizeof(cmd),
-            "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
+            "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
             (add ? "A" : "D"),
             intIface, extIface);
     if (runCmd(IPTABLES_PATH, cmd) && add) {
         // bail on error, but only if adding
         snprintf(cmd, sizeof(cmd),
-                "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
+                "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
                 (!add ? "A" : "D"),
                 extIface, intIface);
         runCmd(IPTABLES_PATH, cmd);
         return -1;
     }
 
-    snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"),
+    snprintf(cmd, sizeof(cmd), "-%s natctrl_FORWARD -i %s -o %s -j RETURN", (add ? "A" : "D"),
             intIface, extIface);
     if (runCmd(IPTABLES_PATH, cmd) && add) {
         // unwind what's been done, but don't care about success - what more could we do?
         snprintf(cmd, sizeof(cmd),
-                "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
+                "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
                 (!add ? "A" : "D"),
                 intIface, extIface);
         runCmd(IPTABLES_PATH, cmd);
 
         snprintf(cmd, sizeof(cmd),
-                 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
+                 "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
                  (!add ? "A" : "D"),
                  extIface, intIface);
         runCmd(IPTABLES_PATH, cmd);
         return -1;
     }
+
+    snprintf(cmd, sizeof(cmd), "-%s natctrl_FORWARD -j DROP", (add ? "A" : "D"),
+            intIface, extIface);
+    runCmd(IPTABLES_PATH, cmd);
+
     return 0;
 }