arc: Move platform2/arc/network/ to platform2/patchpanel

Next step in the arc-networkd -> patchpanel rename, this patch moves the
location of the code.

BUG=b:151879931
TEST=units,flashed image to atlas
TEST=tasts arc.PlayStore, crostini.LaunchTerminal.download

Change-Id: I1b5cf8d670e1631d46f6449b725395157bf88dde
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2115863
Tested-by: Garrick Evans <garrick@chromium.org>
Commit-Queue: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Reviewed-by: Eric Caruso <ejcaruso@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/multicast_proxy.cc b/patchpanel/multicast_proxy.cc
new file mode 100644
index 0000000..45294fe
--- /dev/null
+++ b/patchpanel/multicast_proxy.cc
@@ -0,0 +1,139 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "patchpanel/multicast_proxy.h"
+
+#include <sysexits.h>
+
+#include <utility>
+
+#include "patchpanel/minijailed_process_runner.h"
+
+namespace patchpanel {
+
+MulticastProxy::MulticastProxy(base::ScopedFD control_fd)
+    : msg_dispatcher_(std::move(control_fd)) {
+  msg_dispatcher_.RegisterFailureHandler(base::Bind(
+      &MulticastProxy::OnParentProcessExit, weak_factory_.GetWeakPtr()));
+
+  msg_dispatcher_.RegisterDeviceMessageHandler(
+      base::Bind(&MulticastProxy::OnDeviceMessage, weak_factory_.GetWeakPtr()));
+}
+
+int MulticastProxy::OnInit() {
+  // Prevent the main process from sending us any signals.
+  if (setsid() < 0) {
+    PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
+    return EX_OSERR;
+  }
+
+  EnterChildProcessJail();
+  return Daemon::OnInit();
+}
+
+void MulticastProxy::Reset() {
+  mdns_fwds_.clear();
+  ssdp_fwds_.clear();
+  bcast_fwds_.clear();
+}
+
+void MulticastProxy::OnParentProcessExit() {
+  LOG(ERROR) << "Quitting because the parent process died";
+  Reset();
+  Quit();
+}
+
+void MulticastProxy::OnDeviceMessage(const DeviceMessage& msg) {
+  const std::string& dev_ifname = msg.dev_ifname();
+  if (dev_ifname.empty()) {
+    LOG(DFATAL) << "Received DeviceMessage w/ empty dev_ifname";
+    return;
+  }
+
+  auto mdns_fwd = mdns_fwds_.find(dev_ifname);
+  auto ssdp_fwd = ssdp_fwds_.find(dev_ifname);
+  auto bcast_fwd = bcast_fwds_.find(dev_ifname);
+
+  if (!msg.has_teardown()) {
+    // Start multicast forwarders.
+    if (mdns_fwd == mdns_fwds_.end()) {
+      LOG(INFO) << "Enabling mDNS forwarding for device " << dev_ifname;
+      auto fwd = std::make_unique<MulticastForwarder>(
+          dev_ifname, kMdnsMcastAddress, kMdnsMcastAddress6, kMdnsPort);
+      mdns_fwd = mdns_fwds_.emplace(dev_ifname, std::move(fwd)).first;
+    }
+
+    LOG(INFO) << "Starting mDNS forwarding between " << dev_ifname << " and "
+              << msg.br_ifname();
+    if (!mdns_fwd->second->AddGuest(msg.br_ifname())) {
+      LOG(WARNING) << "mDNS forwarder could not be started on " << dev_ifname;
+    }
+
+    if (ssdp_fwd == ssdp_fwds_.end()) {
+      LOG(INFO) << "Enabling SSDP forwarding for device " << dev_ifname;
+      auto fwd = std::make_unique<MulticastForwarder>(
+          dev_ifname, kSsdpMcastAddress, kSsdpMcastAddress6, kSsdpPort);
+      ssdp_fwd = ssdp_fwds_.emplace(dev_ifname, std::move(fwd)).first;
+    }
+
+    LOG(INFO) << "Starting SSDP forwarding between " << dev_ifname << " and "
+              << msg.br_ifname();
+    if (!ssdp_fwd->second->AddGuest(msg.br_ifname())) {
+      LOG(WARNING) << "SSDP forwarder could not be started on " << dev_ifname;
+    }
+
+    if (bcast_fwd == bcast_fwds_.end()) {
+      LOG(INFO) << "Enabling broadcast forwarding for device " << dev_ifname;
+      auto fwd = std::make_unique<BroadcastForwarder>(dev_ifname);
+      bcast_fwd = bcast_fwds_.emplace(dev_ifname, std::move(fwd)).first;
+    }
+
+    LOG(INFO) << "Starting broadcast forwarding between " << dev_ifname
+              << " and " << msg.br_ifname();
+    if (!bcast_fwd->second->AddGuest(msg.br_ifname())) {
+      LOG(WARNING) << "SSDP forwarder could not be started on " << dev_ifname;
+    }
+
+    return;
+  }
+
+  if (msg.has_br_ifname()) {
+    // A bridge interface is removed.
+    if (mdns_fwd != mdns_fwds_.end()) {
+      LOG(INFO) << "Disabling mDNS forwarding between " << dev_ifname << " and "
+                << msg.br_ifname();
+      mdns_fwd->second->RemoveGuest(msg.br_ifname());
+    }
+    if (ssdp_fwd != ssdp_fwds_.end()) {
+      LOG(INFO) << "Disabling SSDP forwarding between " << dev_ifname << " and "
+                << msg.br_ifname();
+      ssdp_fwd->second->RemoveGuest(msg.br_ifname());
+    }
+    if (bcast_fwd != bcast_fwds_.end()) {
+      LOG(INFO) << "Disabling broadcast forwarding between " << dev_ifname
+                << " and " << msg.br_ifname();
+      bcast_fwd->second->RemoveGuest(msg.br_ifname());
+    }
+    return;
+  }
+
+  // A physical interface is removed.
+  if (mdns_fwd != mdns_fwds_.end()) {
+    LOG(INFO) << "Disabling mDNS forwarding for physical interface "
+              << dev_ifname;
+    mdns_fwds_.erase(mdns_fwd);
+  }
+  if (ssdp_fwd != ssdp_fwds_.end()) {
+    LOG(INFO) << "Disabling SSDP forwarding for physical interface "
+              << dev_ifname;
+    ssdp_fwds_.erase(ssdp_fwd);
+  }
+  if (bcast_fwd != bcast_fwds_.end()) {
+    LOG(INFO) << "Disabling broadcast forwarding for physical interface "
+              << dev_ifname;
+    bcast_fwds_.erase(bcast_fwd);
+  }
+}
+
+}  // namespace patchpanel