Allow connectivity-critical packets in data saver mode.

This makes IPv6 work on metered wifi networks. Without this:

1. We reject incoming RAs, so we lose connectivity when the RA
   parameters expire.
2. We reject incoming NAs, so we get NUD failures.

Bug: 66015813
Test: angler builds, boots
Test: netd_{unit,integration}_test pass
Test: CtsHostsideNetworkTests tests pass
Change-Id: I033040ef0b91c22035e29c636123cd41ab1967ec
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 1484187..04e5d75 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -52,6 +52,7 @@
 
 #include <netdutils/Syscalls.h>
 #include "BandwidthController.h"
+#include "FirewallController.h" /* For makeCriticalCommands */
 #include "NetdConstants.h"
 
 /* Alphabetical */
@@ -241,12 +242,25 @@
     return 0;
 }
 
-int BandwidthController::enableDataSaver(bool enable) {
-    std::string cmd = StringPrintf(
+std::string BandwidthController::makeDataSaverCommand(IptablesTarget target, bool enable) {
+    std::string cmd;
+    const char *chainName = "bw_data_saver";
+    const char *op = jumpToString(enable ? IptJumpReject : IptJumpReturn);
+    std::string criticalCommands = enable ?
+            FirewallController::makeCriticalCommands(target, chainName) : "";
+    StringAppendF(&cmd,
         "*filter\n"
-        "-R bw_data_saver 1%s\n"
-        "COMMIT\n", jumpToString(enable ? IptJumpReject : IptJumpReturn));
-    return iptablesRestoreFunction(V4V6, cmd, nullptr);
+        ":%s -\n"
+        "%s"
+        "-A %s%s\n"
+        "COMMIT\n", chainName, criticalCommands.c_str(), chainName, op);
+    return cmd;
+}
+
+int BandwidthController::enableDataSaver(bool enable) {
+    int ret = iptablesRestoreFunction(V4, makeDataSaverCommand(V4, enable), nullptr);
+    ret |= iptablesRestoreFunction(V6, makeDataSaverCommand(V6, enable), nullptr);
+    return ret;
 }
 
 int BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {