Jason Jeremy Iman | 429b079 | 2020-03-13 15:34:16 +0900 | [diff] [blame] | 1 | // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame] | 5 | #include "patchpanel/multicast_proxy.h" |
Jason Jeremy Iman | 429b079 | 2020-03-13 15:34:16 +0900 | [diff] [blame] | 6 | |
| 7 | #include <sysexits.h> |
| 8 | |
| 9 | #include <utility> |
| 10 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame] | 11 | #include "patchpanel/minijailed_process_runner.h" |
Jason Jeremy Iman | 429b079 | 2020-03-13 15:34:16 +0900 | [diff] [blame] | 12 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame] | 13 | namespace patchpanel { |
Jason Jeremy Iman | 429b079 | 2020-03-13 15:34:16 +0900 | [diff] [blame] | 14 | |
| 15 | MulticastProxy::MulticastProxy(base::ScopedFD control_fd) |
| 16 | : msg_dispatcher_(std::move(control_fd)) { |
| 17 | msg_dispatcher_.RegisterFailureHandler(base::Bind( |
| 18 | &MulticastProxy::OnParentProcessExit, weak_factory_.GetWeakPtr())); |
| 19 | |
| 20 | msg_dispatcher_.RegisterDeviceMessageHandler( |
| 21 | base::Bind(&MulticastProxy::OnDeviceMessage, weak_factory_.GetWeakPtr())); |
| 22 | } |
| 23 | |
| 24 | int MulticastProxy::OnInit() { |
| 25 | // Prevent the main process from sending us any signals. |
| 26 | if (setsid() < 0) { |
| 27 | PLOG(ERROR) << "Failed to created a new session with setsid; exiting"; |
| 28 | return EX_OSERR; |
| 29 | } |
| 30 | |
| 31 | EnterChildProcessJail(); |
| 32 | return Daemon::OnInit(); |
| 33 | } |
| 34 | |
| 35 | void MulticastProxy::Reset() { |
| 36 | mdns_fwds_.clear(); |
| 37 | ssdp_fwds_.clear(); |
| 38 | bcast_fwds_.clear(); |
| 39 | } |
| 40 | |
| 41 | void MulticastProxy::OnParentProcessExit() { |
| 42 | LOG(ERROR) << "Quitting because the parent process died"; |
| 43 | Reset(); |
| 44 | Quit(); |
| 45 | } |
| 46 | |
| 47 | void MulticastProxy::OnDeviceMessage(const DeviceMessage& msg) { |
| 48 | const std::string& dev_ifname = msg.dev_ifname(); |
| 49 | if (dev_ifname.empty()) { |
| 50 | LOG(DFATAL) << "Received DeviceMessage w/ empty dev_ifname"; |
| 51 | return; |
| 52 | } |
| 53 | |
| 54 | auto mdns_fwd = mdns_fwds_.find(dev_ifname); |
| 55 | auto ssdp_fwd = ssdp_fwds_.find(dev_ifname); |
| 56 | auto bcast_fwd = bcast_fwds_.find(dev_ifname); |
| 57 | |
| 58 | if (!msg.has_teardown()) { |
| 59 | // Start multicast forwarders. |
| 60 | if (mdns_fwd == mdns_fwds_.end()) { |
| 61 | LOG(INFO) << "Enabling mDNS forwarding for device " << dev_ifname; |
| 62 | auto fwd = std::make_unique<MulticastForwarder>( |
| 63 | dev_ifname, kMdnsMcastAddress, kMdnsMcastAddress6, kMdnsPort); |
| 64 | mdns_fwd = mdns_fwds_.emplace(dev_ifname, std::move(fwd)).first; |
| 65 | } |
| 66 | |
| 67 | LOG(INFO) << "Starting mDNS forwarding between " << dev_ifname << " and " |
| 68 | << msg.br_ifname(); |
| 69 | if (!mdns_fwd->second->AddGuest(msg.br_ifname())) { |
| 70 | LOG(WARNING) << "mDNS forwarder could not be started on " << dev_ifname; |
| 71 | } |
| 72 | |
| 73 | if (ssdp_fwd == ssdp_fwds_.end()) { |
| 74 | LOG(INFO) << "Enabling SSDP forwarding for device " << dev_ifname; |
| 75 | auto fwd = std::make_unique<MulticastForwarder>( |
| 76 | dev_ifname, kSsdpMcastAddress, kSsdpMcastAddress6, kSsdpPort); |
| 77 | ssdp_fwd = ssdp_fwds_.emplace(dev_ifname, std::move(fwd)).first; |
| 78 | } |
| 79 | |
| 80 | LOG(INFO) << "Starting SSDP forwarding between " << dev_ifname << " and " |
| 81 | << msg.br_ifname(); |
| 82 | if (!ssdp_fwd->second->AddGuest(msg.br_ifname())) { |
| 83 | LOG(WARNING) << "SSDP forwarder could not be started on " << dev_ifname; |
| 84 | } |
| 85 | |
| 86 | if (bcast_fwd == bcast_fwds_.end()) { |
| 87 | LOG(INFO) << "Enabling broadcast forwarding for device " << dev_ifname; |
| 88 | auto fwd = std::make_unique<BroadcastForwarder>(dev_ifname); |
| 89 | bcast_fwd = bcast_fwds_.emplace(dev_ifname, std::move(fwd)).first; |
| 90 | } |
| 91 | |
| 92 | LOG(INFO) << "Starting broadcast forwarding between " << dev_ifname |
| 93 | << " and " << msg.br_ifname(); |
| 94 | if (!bcast_fwd->second->AddGuest(msg.br_ifname())) { |
| 95 | LOG(WARNING) << "SSDP forwarder could not be started on " << dev_ifname; |
| 96 | } |
| 97 | |
| 98 | return; |
| 99 | } |
| 100 | |
| 101 | if (msg.has_br_ifname()) { |
| 102 | // A bridge interface is removed. |
| 103 | if (mdns_fwd != mdns_fwds_.end()) { |
| 104 | LOG(INFO) << "Disabling mDNS forwarding between " << dev_ifname << " and " |
| 105 | << msg.br_ifname(); |
| 106 | mdns_fwd->second->RemoveGuest(msg.br_ifname()); |
| 107 | } |
| 108 | if (ssdp_fwd != ssdp_fwds_.end()) { |
| 109 | LOG(INFO) << "Disabling SSDP forwarding between " << dev_ifname << " and " |
| 110 | << msg.br_ifname(); |
| 111 | ssdp_fwd->second->RemoveGuest(msg.br_ifname()); |
| 112 | } |
| 113 | if (bcast_fwd != bcast_fwds_.end()) { |
| 114 | LOG(INFO) << "Disabling broadcast forwarding between " << dev_ifname |
| 115 | << " and " << msg.br_ifname(); |
| 116 | bcast_fwd->second->RemoveGuest(msg.br_ifname()); |
| 117 | } |
| 118 | return; |
| 119 | } |
| 120 | |
| 121 | // A physical interface is removed. |
| 122 | if (mdns_fwd != mdns_fwds_.end()) { |
| 123 | LOG(INFO) << "Disabling mDNS forwarding for physical interface " |
| 124 | << dev_ifname; |
| 125 | mdns_fwds_.erase(mdns_fwd); |
| 126 | } |
| 127 | if (ssdp_fwd != ssdp_fwds_.end()) { |
| 128 | LOG(INFO) << "Disabling SSDP forwarding for physical interface " |
| 129 | << dev_ifname; |
| 130 | ssdp_fwds_.erase(ssdp_fwd); |
| 131 | } |
| 132 | if (bcast_fwd != bcast_fwds_.end()) { |
| 133 | LOG(INFO) << "Disabling broadcast forwarding for physical interface " |
| 134 | << dev_ifname; |
| 135 | bcast_fwds_.erase(bcast_fwd); |
| 136 | } |
| 137 | } |
| 138 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame] | 139 | } // namespace patchpanel |