Remove support for filtering tether stats.

The framework does not use this filtering, so it's just
dead code. It also requires that NatController publicly
expose its list of interface pairs.

Also make the parsing code a bit stricter - for example, return
an error if any of the lines (except the headers) fail to parse.

Bug: 32163131
Bug: 64995262
Test: bullhead builds and boots
Test: netd_{unit,integration}_test pass
Test: output of "adb shell ndc bandwidth gettetherstats" looks correct
Change-Id: Ib7440f935809c59d8b48396764cc63eb95f509b4
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index 094170f..543eaef 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -628,11 +628,8 @@
  *          0        0 RETURN     all      wlan0  rmnet_data0  ::/0                 ::/0
  *          0        0 RETURN     all      rmnet_data0 wlan0   ::/0                 ::/0
  *
- * It results in an error if invoked and no tethering counter rules exist. The constraint
- * helps detect complete parsing failure.
  */
-int TetherController::addForwardChainStats(const TetherStats& filter,
-                                           TetherStatsList& statsList,
+int TetherController::addForwardChainStats(TetherStatsList& statsList,
                                            const std::string& statsOutput,
                                            std::string &extraProcessingInfo) {
     int res;
@@ -642,17 +639,23 @@
     char rest[MAX_IPT_OUTPUT_LINE_LEN];
 
     TetherStats stats;
+    const TetherStats empty;
     const char *buffPtr;
     int64_t packets, bytes;
     int statsFound = 0;
 
-    bool filterPair = filter.intIface[0] && filter.extIface[0];
-
-    ALOGV("filter: %s",  filter.getStatsLine().c_str());
-
-    stats = filter;
-
     std::stringstream stream(statsOutput);
+
+    // Skip headers.
+    for (int i = 0; i < 2; i++) {
+        std::getline(stream, statsLine, '\n');
+        extraProcessingInfo += statsLine + "\n";
+        if (statsLine.empty()) {
+            ALOGE("Empty header while parsing tethering stats");
+            return -1;
+        }
+    }
+
     while (std::getline(stream, statsLine, '\n')) {
         buffPtr = statsLine.c_str();
 
@@ -675,66 +678,34 @@
         extraProcessingInfo += "\n";
 
         if (res != 5) {
-            continue;
+            return -EREMOTEIO;
         }
         /*
          * The following assumes that the 1st rule has in:extIface out:intIface,
          * which is what TetherController sets up.
-         * If not filtering, the 1st match rx, and sets up the pair for the tx side.
+         * The 1st matches rx, and sets up the pair for the tx side.
          */
-        if (filter.intIface[0] && filter.extIface[0]) {
-            if (filter.intIface == iface0 && filter.extIface == iface1) {
-                ALOGV("2Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.rxPackets = packets;
-                stats.rxBytes = bytes;
-            } else if (filter.intIface == iface1 && filter.extIface == iface0) {
-                ALOGV("2Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.txPackets = packets;
-                stats.txBytes = bytes;
-            }
-        } else if (filter.intIface[0] || filter.extIface[0]) {
-            if (filter.intIface == iface0 || filter.extIface == iface1) {
-                ALOGV("1Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.intIface = iface0;
-                stats.extIface = iface1;
-                stats.rxPackets = packets;
-                stats.rxBytes = bytes;
-            } else if (filter.intIface == iface1 || filter.extIface == iface0) {
-                ALOGV("1Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.intIface = iface1;
-                stats.extIface = iface0;
-                stats.txPackets = packets;
-                stats.txBytes = bytes;
-            }
-        } else /* if (!filter.intFace[0] && !filter.extIface[0]) */ {
-            if (!stats.intIface[0]) {
-                ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.intIface = iface0;
-                stats.extIface = iface1;
-                stats.rxPackets = packets;
-                stats.rxBytes = bytes;
-            } else if (stats.intIface == iface1 && stats.extIface == iface0) {
-                ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
-                stats.txPackets = packets;
-                stats.txBytes = bytes;
-            }
+        if (!stats.intIface[0]) {
+            ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
+            stats.intIface = iface0;
+            stats.extIface = iface1;
+            stats.rxPackets = packets;
+            stats.rxBytes = bytes;
+        } else if (stats.intIface == iface1 && stats.extIface == iface0) {
+            ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
+            stats.txPackets = packets;
+            stats.txBytes = bytes;
         }
         if (stats.rxBytes != -1 && stats.txBytes != -1) {
-            ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64" filterPair=%d", stats.rxBytes, stats.txBytes, filterPair);
+            ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64, stats.rxBytes, stats.txBytes);
             addStats(statsList, stats);
-            if (filterPair) {
-                return 0;
-            } else {
-                statsFound++;
-                stats = filter;
-            }
+            statsFound++;
+            stats = empty;
         }
     }
 
     /* It is always an error to find only one side of the stats. */
-    /* It is an error to find nothing when not filtering. */
-    if (((stats.rxBytes == -1) != (stats.txBytes == -1)) ||
-        (!statsFound && !filterPair)) {
+    if (((stats.rxBytes == -1) != (stats.txBytes == -1)) || !statsFound) {
         return -1;
     }
     return 0;
@@ -747,40 +718,28 @@
     return msg;
 }
 
-int TetherController::getTetherStats(SocketClient *cli, TetherStats& filter,
-                                        std::string &extraProcessingInfo) {
-    int res = 0;
-
+int TetherController::getTetherStats(SocketClient *cli, std::string &extraProcessingInfo) {
     TetherStatsList statsList;
 
     for (const IptablesTarget target : {V4, V6}) {
         std::string statsString;
-        res = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString);
-        if (res != 0) {
-            ALOGE("Failed to run %s err=%d", GET_TETHER_STATS_COMMAND.c_str(), res);
+        if (int ret = iptablesRestoreFunction(target, GET_TETHER_STATS_COMMAND, &statsString)) {
+            ALOGE("Failed to run %s err=%d", GET_TETHER_STATS_COMMAND.c_str(), ret);
             return -1;
         }
 
-        res = addForwardChainStats(filter, statsList, statsString, extraProcessingInfo);
-        if (res != 0) {
-            return res;
+        if (int ret = addForwardChainStats(statsList, statsString, extraProcessingInfo)) {
+            return ret;
         }
     }
 
-    if (filter.intIface[0] && filter.extIface[0] && statsList.size() == 1) {
-        cli->sendMsg(ResponseCode::TetheringStatsResult,
-                     statsList[0].getStatsLine().c_str(), false);
-    } else {
-        for (const auto& stats: statsList) {
-            cli->sendMsg(ResponseCode::TetheringStatsListResult,
-                         stats.getStatsLine().c_str(), false);
-        }
-        if (res == 0) {
-            cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
-        }
+    for (const auto& stats: statsList) {
+        cli->sendMsg(ResponseCode::TetheringStatsListResult,
+                     stats.getStatsLine().c_str(), false);
     }
+    cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
 
-    return res;
+    return 0;
 }
 
 }  // namespace net