Nat-related commands porting

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

Change-Id: I14e80377bc1b7c08993c3cf8fbf2b6fd0f99f4ba
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 6a40ba2..e0dc25e 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -652,12 +652,13 @@
 
 int BandwidthController::setGlobalAlert(int64_t bytes) {
     const char *alertName = ALERT_GLOBAL_NAME;
-    int res = 0;
 
     if (!bytes) {
         ALOGE("Invalid bytes value. 1..max_int64.");
         return -ERANGE;
     }
+
+    int res = 0;
     if (mGlobalAlertBytes) {
         res = updateQuota(alertName, bytes);
     } else {
@@ -676,7 +677,6 @@
 
 int BandwidthController::setGlobalAlertInForwardChain() {
     const char *alertName = ALERT_GLOBAL_NAME;
-    int res = 0;
 
     mGlobalAlertTetherCount++;
     ALOGV("setGlobalAlertInForwardChain(): %d tether", mGlobalAlertTetherCount);
@@ -691,19 +691,20 @@
     }
 
     /* We only add the rule if this was the 1st tether added. */
-    res = runIptablesAlertFwdCmd(IptOpInsert, alertName, mGlobalAlertBytes);
-    return res;
+    return (runIptablesAlertFwdCmd(IptOpInsert, alertName, mGlobalAlertBytes) == 0) ? 0
+                                                                                    : -EREMOTEIO;
 }
 
 int BandwidthController::removeGlobalAlert() {
 
     const char *alertName = ALERT_GLOBAL_NAME;
-    int res = 0;
 
     if (!mGlobalAlertBytes) {
         ALOGE("No prior alert set");
         return -1;
     }
+
+    int res = 0;
     res = runIptablesAlertCmd(IptOpDelete, alertName, mGlobalAlertBytes);
     if (mGlobalAlertTetherCount) {
         res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes);
@@ -713,12 +714,11 @@
 }
 
 int BandwidthController::removeGlobalAlertInForwardChain() {
-    int res = 0;
     const char *alertName = ALERT_GLOBAL_NAME;
 
     if (!mGlobalAlertTetherCount) {
         ALOGE("No prior alert set");
-        return -1;
+        return -ENOENT;
     }
 
     mGlobalAlertTetherCount--;
@@ -732,8 +732,8 @@
     }
 
     /* We only detete the rule if this was the last tether removed. */
-    res = runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes);
-    return res;
+    return (runIptablesAlertFwdCmd(IptOpDelete, alertName, mGlobalAlertBytes) == 0) ? 0
+                                                                                    : -EREMOTEIO;
 }
 
 int BandwidthController::setSharedAlert(int64_t bytes) {
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index c993f30..7647e20 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -1487,5 +1487,31 @@
     return statusFromErrcode(res);
 }
 
+binder::Status NetdNativeService::tetherAddForward(const std::string& intIface,
+                                                   const std::string& extIface) {
+    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
+
+    int res = gCtls->tetherCtrl.enableNat(intIface.c_str(), extIface.c_str());
+    if (!res) {
+        std::lock_guard lock(gCtls->bandwidthCtrl.lock);
+        res = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
+    }
+    gLog.log(entry.returns(res).withAutomaticDuration());
+    return statusFromErrcode(res);
+}
+
+binder::Status NetdNativeService::tetherRemoveForward(const std::string& intIface,
+                                                      const std::string& extIface) {
+    NETD_LOCKING_RPC(NETWORK_STACK, gCtls->tetherCtrl.lock);
+    std::lock_guard lock(gCtls->bandwidthCtrl.lock);
+    auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).args(intIface, extIface);
+
+    int res = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
+    res |= gCtls->tetherCtrl.disableNat(intIface.c_str(), extIface.c_str());
+    gLog.log(entry.returns(res).withAutomaticDuration());
+    return statusFromErrcode(res);
+}
+
 }  // namespace net
 }  // namespace android
diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
index 7ae2e34..62f9b3f 100644
--- a/server/NetdNativeService.h
+++ b/server/NetdNativeService.h
@@ -259,6 +259,11 @@
                                             const std::string& toIface) override;
     binder::Status ipfwdRemoveInterfaceForward(const std::string& fromIface,
                                                const std::string& toIface) override;
+    // Tether-forward-related commands
+    binder::Status tetherAddForward(const std::string& intIface,
+                                    const std::string& extIface) override;
+    binder::Status tetherRemoveForward(const std::string& intIface,
+                                       const std::string& extIface) override;
 
   private:
     std::vector<uid_t> intsToUids(const std::vector<int32_t>& intUids);
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index b11f4dc..49c1b7e 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -531,15 +531,13 @@
     ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
 
     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
-        errno = ENODEV;
-        return -1;
+        return -ENODEV;
     }
 
     /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
     if (!strcmp(intIface, extIface)) {
         ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
-        errno = EINVAL;
-        return -1;
+        return -EINVAL;
     }
 
     if (isForwardingPairEnabled(intIface, extIface)) {
@@ -561,7 +559,7 @@
                 // unwind what's been done, but don't care about success - what more could we do?
                 setDefaults();
             }
-            return -1;
+            return -EREMOTEIO;
         }
     }
 
@@ -570,8 +568,7 @@
         if (!isAnyForwardingPairEnabled()) {
             setDefaults();
         }
-        errno = ENODEV;
-        return -1;
+        return -ENODEV;
     }
 
     return 0;
@@ -678,7 +675,7 @@
         "%s %s -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
         "COMMIT\n", op, LOCAL_RAW_PREROUTING, intIface);
     if (iptablesRestoreFunction(V6, rpfilterCmd, nullptr) == -1 && add) {
-        return -1;
+        return -EREMOTEIO;
     }
 
     std::vector<std::string> v4 = {
@@ -727,7 +724,7 @@
         if (add) {
             setForwardRules(false, intIface, extIface);
         }
-        return -1;
+        return -EREMOTEIO;
     }
 
     if (add) {
@@ -741,8 +738,7 @@
 
 int TetherController::disableNat(const char* intIface, const char* extIface) {
     if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
-        errno = ENODEV;
-        return -1;
+        return -ENODEV;
     }
 
     setForwardRules(false, intIface, extIface);
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index 94dcad2..a6905b1 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -1133,4 +1133,19 @@
     *         cause of the the failure.
     */
     void interfaceSetMtu(in @utf8InCpp String ifName, int mtu);
+   /**
+    * Add forwarding rule/stats on given interface.
+    *
+    * @param intIface downstream interface
+    * @param extIface upstream interface
+    */
+    void tetherAddForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface);
+
+   /**
+    * Remove forwarding rule/stats on given interface.
+    *
+    * @param intIface downstream interface
+    * @param extIface upstream interface
+    */
+    void tetherRemoveForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface);
 }