patchpanel: Move wwan masquerade from script

BUG=b:156200410
TEST=units

Change-Id: I7397b98c1cbed74eea0debaff1ad2c918e7be318
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2214844
Tested-by: Garrick Evans <garrick@chromium.org>
Commit-Queue: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/datapath.cc b/patchpanel/datapath.cc
index 80faf15..aadd1df 100644
--- a/patchpanel/datapath.cc
+++ b/patchpanel/datapath.cc
@@ -446,6 +446,16 @@
                                        "1", "-j", "ACCEPT", "-w"});
 }
 
+bool Datapath::AddInterfaceSNAT(const std::string& ifname) {
+  return process_runner_->iptables("nat", {"-A", "POSTROUTING", "-o", ifname,
+                                           "-j", "MASQUERADE", "-w"}) == 0;
+}
+
+void Datapath::RemoveInterfaceSNAT(const std::string& ifname) {
+  process_runner_->iptables(
+      "nat", {"-D", "POSTROUTING", "-o", ifname, "-j", "MASQUERADE", "-w"});
+}
+
 bool Datapath::AddOutboundIPv4SNATMark(const std::string& ifname) {
   return process_runner_->iptables(
              "mangle", {"-A", "PREROUTING", "-i", ifname, "-j", "MARK",
diff --git a/patchpanel/datapath.h b/patchpanel/datapath.h
index 3dc5dbd..dcdcf04 100644
--- a/patchpanel/datapath.h
+++ b/patchpanel/datapath.h
@@ -122,6 +122,9 @@
   virtual bool AddSNATMarkRules();
   virtual void RemoveSNATMarkRules();
 
+  virtual bool AddInterfaceSNAT(const std::string& ifname);
+  virtual void RemoveInterfaceSNAT(const std::string& ifname);
+
   // Create (or delete) a mangle PREROUTING rule for marking IPv4 traffic
   // outgoing of |ifname| with the SNAT fwmark value 0x1.
   // TODO(hugobenichi) Refer to RoutingService to obtain the fwmark value and
diff --git a/patchpanel/datapath_test.cc b/patchpanel/datapath_test.cc
index 43ea032..1aebb4f 100644
--- a/patchpanel/datapath_test.cc
+++ b/patchpanel/datapath_test.cc
@@ -548,6 +548,26 @@
   datapath.RemoveForwardEstablishedRule();
 }
 
+TEST(DatapathTest, AddInterfaceSNAT) {
+  MockProcessRunner runner;
+  EXPECT_CALL(runner, iptables(StrEq("nat"),
+                               ElementsAre("-A", "POSTROUTING", "-o", "wwan+",
+                                           "-j", "MASQUERADE", "-w"),
+                               true));
+  Datapath datapath(&runner);
+  datapath.AddInterfaceSNAT("wwan+");
+}
+
+TEST(DatapathTest, RemoveInterfaceSNAT) {
+  MockProcessRunner runner;
+  EXPECT_CALL(runner, iptables(StrEq("nat"),
+                               ElementsAre("-D", "POSTROUTING", "-o", "wwan+",
+                                           "-j", "MASQUERADE", "-w"),
+                               true));
+  Datapath datapath(&runner);
+  datapath.RemoveInterfaceSNAT("wwan+");
+}
+
 TEST(DatapathTest, ArcVethHostName) {
   EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
   EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
diff --git a/patchpanel/init/patchpanel.conf b/patchpanel/init/patchpanel.conf
index e7bdb27..10e8f31 100644
--- a/patchpanel/init/patchpanel.conf
+++ b/patchpanel/init/patchpanel.conf
@@ -25,11 +25,6 @@
   # need to be explicitly dropped.
   iptables -A FORWARD -m mark --mark 1 -m state --state INVALID -j DROP -w
 
-  # TODO(chromium:898210): Move interface-specific masquerading setup to shill;
-  # such that we can better set up the masquerade rules based on connection
-  # type rather than interface names.
-  iptables -t nat -A POSTROUTING -o wwan+ -j MASQUERADE -w
-
   # This marks packets from _all_ interfaces starting with vmtap, since
   # they all belong to termina, and will all want to be NAT'ed.
   iptables -t mangle -A PREROUTING -i vmtap+ -j MARK --set-mark 1 -w
@@ -45,10 +40,5 @@
   echo "Stopped patchpaneld"
   echo "Tearing down NAT and IP forwarding"
   iptables -t mangle -D PREROUTING -i vmtap+ -j MARK --set-mark 1 -w
-
-  # TODO(chromium:898210): Move interface-specific masquerading setup to shill
-  # such that we can better set up the masquerade rules based on connection
-  # type rather than interface names.
-  iptables -t nat -D POSTROUTING -o wwan+ -j MASQUERADE -w
 } 2>&1 | logger -t "${UPSTART_JOB}"
 end script # post-stop
diff --git a/patchpanel/manager.cc b/patchpanel/manager.cc
index ff64967..c77cf03 100644
--- a/patchpanel/manager.cc
+++ b/patchpanel/manager.cc
@@ -254,6 +254,13 @@
                << " connections.";
   }
 
+  // TODO(chromium:898210): Move interface-specific masquerading setup to shill;
+  // such that we can better set up the masquerade rules based on connection
+  // type rather than interface names.
+  if (!datapath_->AddInterfaceSNAT("wwan+")) {
+    LOG(ERROR) << "Failed to set up wifi masquerade";
+  }
+
   routing_svc_ = std::make_unique<RoutingService>();
 
   nd_proxy_->RegisterDeviceMessageHandler(base::Bind(
@@ -285,6 +292,7 @@
   for (const int fdkey : connected_namespaces_fdkeys)
     DisconnectNamespace(fdkey);
 
+  datapath_->RemoveInterfaceSNAT("wwan+");
   datapath_->RemoveForwardEstablishedRule();
   datapath_->RemoveSNATMarkRules();