blob: 7aa6cecca820168a3c7fefc152c29107a660ba04 [file] [log] [blame]
Jason Jeremy Iman429b0792020-03-13 15:34:16 +09001// 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 Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/multicast_proxy.h"
Jason Jeremy Iman429b0792020-03-13 15:34:16 +09006
7#include <sysexits.h>
8
9#include <utility>
10
Garrick Evans3388a032020-03-24 11:25:55 +090011#include "patchpanel/minijailed_process_runner.h"
Jason Jeremy Iman429b0792020-03-13 15:34:16 +090012
Garrick Evans3388a032020-03-24 11:25:55 +090013namespace patchpanel {
Jason Jeremy Iman429b0792020-03-13 15:34:16 +090014
15MulticastProxy::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
24int 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
35void MulticastProxy::Reset() {
36 mdns_fwds_.clear();
37 ssdp_fwds_.clear();
38 bcast_fwds_.clear();
39}
40
41void MulticastProxy::OnParentProcessExit() {
42 LOG(ERROR) << "Quitting because the parent process died";
43 Reset();
44 Quit();
45}
46
47void 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())) {
Hugo Benichi3cfadbe2020-08-14 11:42:27 +090070 LOG(WARNING) << "mDNS forwarder could not be started between "
71 << dev_ifname << " and " << msg.br_ifname();
Jason Jeremy Iman429b0792020-03-13 15:34:16 +090072 }
73
74 if (ssdp_fwd == ssdp_fwds_.end()) {
75 LOG(INFO) << "Enabling SSDP forwarding for device " << dev_ifname;
76 auto fwd = std::make_unique<MulticastForwarder>(
77 dev_ifname, kSsdpMcastAddress, kSsdpMcastAddress6, kSsdpPort);
78 ssdp_fwd = ssdp_fwds_.emplace(dev_ifname, std::move(fwd)).first;
79 }
80
81 LOG(INFO) << "Starting SSDP forwarding between " << dev_ifname << " and "
82 << msg.br_ifname();
83 if (!ssdp_fwd->second->AddGuest(msg.br_ifname())) {
Hugo Benichi3cfadbe2020-08-14 11:42:27 +090084 LOG(WARNING) << "SSDP forwarder could not be started on " << dev_ifname
85 << " and " << msg.br_ifname();
Jason Jeremy Iman429b0792020-03-13 15:34:16 +090086 }
87
88 if (bcast_fwd == bcast_fwds_.end()) {
89 LOG(INFO) << "Enabling broadcast forwarding for device " << dev_ifname;
90 auto fwd = std::make_unique<BroadcastForwarder>(dev_ifname);
91 bcast_fwd = bcast_fwds_.emplace(dev_ifname, std::move(fwd)).first;
92 }
93
94 LOG(INFO) << "Starting broadcast forwarding between " << dev_ifname
95 << " and " << msg.br_ifname();
96 if (!bcast_fwd->second->AddGuest(msg.br_ifname())) {
Hugo Benichi3cfadbe2020-08-14 11:42:27 +090097 LOG(WARNING) << "Broadcast forwarder could not be started on "
98 << dev_ifname << " and " << msg.br_ifname();
Jason Jeremy Iman429b0792020-03-13 15:34:16 +090099 }
100
101 return;
102 }
103
104 if (msg.has_br_ifname()) {
105 // A bridge interface is removed.
106 if (mdns_fwd != mdns_fwds_.end()) {
107 LOG(INFO) << "Disabling mDNS forwarding between " << dev_ifname << " and "
108 << msg.br_ifname();
109 mdns_fwd->second->RemoveGuest(msg.br_ifname());
110 }
111 if (ssdp_fwd != ssdp_fwds_.end()) {
112 LOG(INFO) << "Disabling SSDP forwarding between " << dev_ifname << " and "
113 << msg.br_ifname();
114 ssdp_fwd->second->RemoveGuest(msg.br_ifname());
115 }
116 if (bcast_fwd != bcast_fwds_.end()) {
117 LOG(INFO) << "Disabling broadcast forwarding between " << dev_ifname
118 << " and " << msg.br_ifname();
119 bcast_fwd->second->RemoveGuest(msg.br_ifname());
120 }
121 return;
122 }
123
124 // A physical interface is removed.
125 if (mdns_fwd != mdns_fwds_.end()) {
126 LOG(INFO) << "Disabling mDNS forwarding for physical interface "
127 << dev_ifname;
128 mdns_fwds_.erase(mdns_fwd);
129 }
130 if (ssdp_fwd != ssdp_fwds_.end()) {
131 LOG(INFO) << "Disabling SSDP forwarding for physical interface "
132 << dev_ifname;
133 ssdp_fwds_.erase(ssdp_fwd);
134 }
135 if (bcast_fwd != bcast_fwds_.end()) {
136 LOG(INFO) << "Disabling broadcast forwarding for physical interface "
137 << dev_ifname;
138 bcast_fwds_.erase(bcast_fwd);
139 }
140}
141
Garrick Evans3388a032020-03-24 11:25:55 +0900142} // namespace patchpanel