Nat-related commands refine

We need this to ensure that the tethering IPCs don't need to grab the
lock in two different controllers

The idea is that always having a global_alert rule in bw_global_alert
chain.
TetherController will enable/disable the reference of bw_global_alert
chain.

[childchain order of filter FORWARD chain]
Chain FORWARD
   nm_mdmprxy_iface_pkt_fwder
   oem_fwd
   fw_FORWARD
   bw_FORWARD
   tetherctrl_FORWARD

--Simple rule comparison--
[Before]
Chain bw_FORWARD
    Alert rule
    ... other rules
Chain tetherctrl_FORWARD
    ... other rules
[After]
Chain bw_FORWARD
    No Alert rule
    ... other rules
Chain tetherctrl_FORWARD
    Jump to bw_global_alert
    ... other rules
Chain bw_global_alert
   Alert rule

The exact rule comparison is shown in the bug.

Bug:119735985
Test: built, flashed, booted
      system/netd/tests/runtests.sh passes

Change-Id: Ibf752d0c8de9170689fc74c89c0424d2642853ec
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index e0dc25e..7e9bff7 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -66,6 +66,7 @@
 const char BandwidthController::LOCAL_OUTPUT[] = "bw_OUTPUT";
 const char BandwidthController::LOCAL_RAW_PREROUTING[] = "bw_raw_PREROUTING";
 const char BandwidthController::LOCAL_MANGLE_POSTROUTING[] = "bw_mangle_POSTROUTING";
+const char BandwidthController::LOCAL_GLOBAL_ALERT[] = "bw_global_alert";
 
 auto BandwidthController::iptablesRestoreFunction = execIptablesRestoreWithOutput;
 
@@ -157,27 +158,27 @@
         "-I bw_penalty_box -m bpf --object-pinned %s -j REJECT", XT_BPF_BLACKLIST_PROG_PATH);
 
 static const std::vector<std::string> IPT_FLUSH_COMMANDS = {
-    /*
-     * Cleanup rules.
-     * Should normally include bw_costly_<iface>, but we rely on the way they are setup
-     * to allow coexistance.
-     */
-    "*filter",
-    ":bw_INPUT -",
-    ":bw_OUTPUT -",
-    ":bw_FORWARD -",
-    ":bw_happy_box -",
-    ":bw_penalty_box -",
-    ":bw_data_saver -",
-    ":bw_costly_shared -",
-    "COMMIT",
-    "*raw",
-    ":bw_raw_PREROUTING -",
-    "COMMIT",
-    "*mangle",
-    ":bw_mangle_POSTROUTING -",
-    COMMIT_AND_CLOSE
-};
+        /*
+         * Cleanup rules.
+         * Should normally include bw_costly_<iface>, but we rely on the way they are setup
+         * to allow coexistance.
+         */
+        "*filter",
+        ":bw_INPUT -",
+        ":bw_OUTPUT -",
+        ":bw_FORWARD -",
+        ":bw_happy_box -",
+        ":bw_penalty_box -",
+        ":bw_data_saver -",
+        ":bw_costly_shared -",
+        ":bw_global_alert -",
+        "COMMIT",
+        "*raw",
+        ":bw_raw_PREROUTING -",
+        "COMMIT",
+        "*mangle",
+        ":bw_mangle_POSTROUTING -",
+        COMMIT_AND_CLOSE};
 
 static const uint32_t uidBillingMask = Fwmark::getUidBillingMask();
 
@@ -215,6 +216,8 @@
 const std::vector<std::string> getBasicAccountingCommands(const bool useBpf) {
     const std::vector<std::string> ipt_basic_accounting_commands = {
             "*filter",
+
+            "-A bw_INPUT -j bw_global_alert",
             // Prevents IPSec double counting (ESP and UDP-encap-ESP respectively)
             "-A bw_INPUT -p esp -j RETURN",
             StringPrintf("-A bw_INPUT -m mark --mark 0x%x/0x%x -j RETURN", uidBillingMask,
@@ -222,6 +225,7 @@
             useBpf ? "" : "-A bw_INPUT -m owner --socket-exists",
             StringPrintf("-A bw_INPUT -j MARK --or-mark 0x%x", uidBillingMask),
 
+            "-A bw_OUTPUT -j bw_global_alert",
             // Prevents IPSec double counting (Tunnel mode and Transport mode,
             // respectively)
             "-A bw_OUTPUT -o " IPSEC_IFACE_PREFIX "+ -j RETURN",
@@ -293,7 +297,6 @@
     mSharedQuotaIfaces.clear();
     mQuotaIfaces.clear();
     mGlobalAlertBytes = 0;
-    mGlobalAlertTetherCount = 0;
     mSharedQuotaBytes = mSharedAlertBytes = 0;
 
     flushCleanTables(false);
@@ -630,20 +633,13 @@
 
     // TODO: consider using an alternate template for the delete that does not include the --quota
     // value. This code works because the --quota value is ignored by deletes
-    StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT", bytes,
-                  alertName.c_str());
-    StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT", bytes,
-                  alertName.c_str());
-    StringAppendF(&alertQuotaCmd, "COMMIT\n");
 
-    return iptablesRestoreFunction(V4V6, alertQuotaCmd, nullptr);
-}
-
-int BandwidthController::runIptablesAlertFwdCmd(IptOp op, const std::string& alertName,
-                                                int64_t bytes) {
-    const char *opFlag = opToString(op);
-    std::string alertQuotaCmd = "*filter\n";
-    StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD", bytes,
+    /*
+     * Add alert rule in bw_global_alert chain, 3 chains might reference bw_global_alert.
+     * bw_INPUT, bw_OUTPUT (added by BandwidthController in enableBandwidthControl)
+     * bw_FORWARD (added by TetherController in setTetherGlobalAlertRule if nat enable/disable)
+     */
+    StringAppendF(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, LOCAL_GLOBAL_ALERT, bytes,
                   alertName.c_str());
     StringAppendF(&alertQuotaCmd, "COMMIT\n");
 
@@ -663,10 +659,6 @@
         res = updateQuota(alertName, bytes);
     } else {
         res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
-        if (mGlobalAlertTetherCount) {
-            ALOGV("setGlobalAlert for %d tether", mGlobalAlertTetherCount);
-            res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
-        }
         if (res) {
             res = -EREMOTEIO;
         }
@@ -675,26 +667,6 @@
     return res;
 }
 
-int BandwidthController::setGlobalAlertInForwardChain() {
-    const char *alertName = ALERT_GLOBAL_NAME;
-
-    mGlobalAlertTetherCount++;
-    ALOGV("setGlobalAlertInForwardChain(): %d tether", mGlobalAlertTetherCount);
-
-    /*
-     * If there is no globalAlert active we are done.
-     * If there is an active globalAlert but this is not the 1st
-     * tether, we are also done.
-     */
-    if (!mGlobalAlertBytes || mGlobalAlertTetherCount != 1) {
-        return 0;
-    }
-
-    /* We only add the rule if this was the 1st tether added. */
-    return (runIptablesAlertFwdCmd(IptOpInsert, alertName, mGlobalAlertBytes) == 0) ? 0
-                                                                                    : -EREMOTEIO;
-}
-
 int BandwidthController::removeGlobalAlert() {
 
     const char *alertName = ALERT_GLOBAL_NAME;
@@ -706,36 +678,10 @@
 
     int res = 0;
     res = runIptablesAlertCmd(IptOpDelete, alertName, mGlobalAlertBytes);
-    if (mGlobalAlertTetherCount) {
-        res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes);
-    }
     mGlobalAlertBytes = 0;
     return res;
 }
 
-int BandwidthController::removeGlobalAlertInForwardChain() {
-    const char *alertName = ALERT_GLOBAL_NAME;
-
-    if (!mGlobalAlertTetherCount) {
-        ALOGE("No prior alert set");
-        return -ENOENT;
-    }
-
-    mGlobalAlertTetherCount--;
-    /*
-     * If there is no globalAlert active we are done.
-     * If there is an active globalAlert but there are more
-     * tethers, we are also done.
-     */
-    if (!mGlobalAlertBytes || mGlobalAlertTetherCount >= 1) {
-        return 0;
-    }
-
-    /* We only detete the rule if this was the last tether removed. */
-    return (runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes) == 0) ? 0
-                                                                                    : -EREMOTEIO;
-}
-
 int BandwidthController::setSharedAlert(int64_t bytes) {
     if (!mSharedQuotaBytes) {
         ALOGE("Need to have a prior shared quota set to set an alert");