Skip to content

Commit dd906dc

Browse files
committed
Validate multicast addresses, pre-filter by allowed network stacks
1 parent 2d54dfe commit dd906dc

File tree

7 files changed

+54
-35
lines changed

7 files changed

+54
-35
lines changed

src/api_config.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,32 +148,29 @@ void api_config::load_from_file(const std::string &filename) {
148148
else
149149
throw std::runtime_error("This ResolveScope setting is unsupported.");
150150

151-
multicast_addresses_.insert(
152-
multicast_addresses_.end(), machine_group.begin(), machine_group.end());
151+
std::vector<std::string> mcasttmp;
152+
153+
mcasttmp.insert(mcasttmp.end(), machine_group.begin(), machine_group.end());
153154
multicast_ttl_ = 0;
154155

155156
if (scope >= link) {
156-
multicast_addresses_.insert(
157-
multicast_addresses_.end(), link_group.begin(), link_group.end());
158-
multicast_addresses_.push_back("FF02:" + ipv6_multicast_group);
157+
mcasttmp.insert(mcasttmp.end(), link_group.begin(), link_group.end());
158+
mcasttmp.push_back("FF02:" + ipv6_multicast_group);
159159
multicast_ttl_ = 1;
160160
}
161161
if (scope >= site) {
162-
multicast_addresses_.insert(
163-
multicast_addresses_.end(), site_group.begin(), site_group.end());
164-
multicast_addresses_.push_back("FF05:" + ipv6_multicast_group);
162+
mcasttmp.insert(mcasttmp.end(), site_group.begin(), site_group.end());
163+
mcasttmp.push_back("FF05:" + ipv6_multicast_group);
165164
multicast_ttl_ = 24;
166165
}
167166
if (scope >= organization) {
168-
multicast_addresses_.insert(
169-
multicast_addresses_.end(), organization_group.begin(), organization_group.end());
170-
multicast_addresses_.push_back("FF08:" + ipv6_multicast_group);
167+
mcasttmp.insert(mcasttmp.end(), organization_group.begin(), organization_group.end());
168+
mcasttmp.push_back("FF08:" + ipv6_multicast_group);
171169
multicast_ttl_ = 32;
172170
}
173171
if (scope >= global) {
174-
multicast_addresses_.insert(
175-
multicast_addresses_.end(), global_group.begin(), global_group.end());
176-
multicast_addresses_.push_back("FF0E:" + ipv6_multicast_group);
172+
mcasttmp.insert(mcasttmp.end(), global_group.begin(), global_group.end());
173+
mcasttmp.push_back("FF0E:" + ipv6_multicast_group);
177174
multicast_ttl_ = 255;
178175
}
179176

@@ -182,7 +179,14 @@ void api_config::load_from_file(const std::string &filename) {
182179
std::vector<std::string> address_override =
183180
parse_set(pt.get("multicast.AddressesOverride", "{}"));
184181
if (ttl_override >= 0) multicast_ttl_ = ttl_override;
185-
if (!address_override.empty()) multicast_addresses_ = address_override;
182+
if (!address_override.empty()) mcasttmp = address_override;
183+
184+
// Parse, validate and store multicast addresses
185+
for (std::vector<std::string>::iterator it = mcasttmp.begin(); it != mcasttmp.end(); ++it) {
186+
ip::address addr = ip::make_address(*it);
187+
if ((addr.is_v4() && allow_ipv4_) || (addr.is_v6() && allow_ipv6_))
188+
multicast_addresses_.push_back(addr);
189+
}
186190

187191
// The network stack requires the source interfaces for multicast packets to be
188192
// specified as IPv4 address or an IPv6 interface index

src/api_config.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <string>
88
#include <vector>
99

10+
namespace ip = lslboost::asio::ip;
11+
1012
namespace lsl {
1113
/**
1214
* A configuration object: holds all the configurable settings of liblsl.
@@ -83,7 +85,7 @@ class api_config {
8385
const std::string &resolve_scope() const { return resolve_scope_; }
8486

8587
/**
86-
* @brief List of multicast addresses on which inlets / outlets advertise/discover streams.
88+
* List of multicast addresses on which inlets / outlets advertise/discover streams.
8789
*
8890
* This is merged from several other config file entries
8991
* (LocalAddresses,SiteAddresses,OrganizationAddresses, GlobalAddresses)
@@ -98,7 +100,7 @@ class api_config {
98100
* department) or organization (e.g., the campus), or at larger scope, multicast addresses
99101
* with the according scope need to be included.
100102
*/
101-
const std::vector<std::string> &multicast_addresses() const { return multicast_addresses_; }
103+
const std::vector<ip::address> &multicast_addresses() const { return multicast_addresses_; }
102104

103105
/**
104106
* @brief The address of the local interface on which to listen to multicast traffic.
@@ -222,7 +224,7 @@ class api_config {
222224
bool allow_random_ports_;
223225
uint16_t multicast_port_;
224226
std::string resolve_scope_;
225-
std::vector<std::string> multicast_addresses_;
227+
std::vector<ip::address> multicast_addresses_;
226228
int multicast_ttl_;
227229
std::string listen_address_;
228230
std::vector<std::string> known_peers_;

src/resolver_impl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ resolver_impl::resolver_impl()
2323
uint16_t mcast_port = cfg_->multicast_port();
2424
for (const auto &mcast_addr : cfg_->multicast_addresses()) {
2525
try {
26-
mcast_endpoints_.emplace_back(ip::make_address(mcast_addr), (uint16_t)mcast_port);
26+
mcast_endpoints_.emplace_back(mcast_addr, mcast_port);
2727
} catch (std::exception &) {}
2828
}
2929

src/stream_outlet_impl.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,15 @@ void stream_outlet_impl::instantiate_stack(tcp tcp_protocol, udp udp_protocol) {
7676
ios_.push_back(std::make_shared<asio::io_context>());
7777
udp_servers_.push_back(std::make_shared<udp_server>(info_, *ios_.back(), udp_protocol));
7878
// create UDP multicast responders
79-
for (const auto &mcastaddr : cfg->multicast_addresses()) {
79+
for (const auto &address : cfg->multicast_addresses()) {
8080
try {
8181
// use only addresses for the protocol that we're supposed to use here
82-
auto address = asio::ip::make_address(mcastaddr);
8382
if (udp_protocol == udp::v4() ? address.is_v4() : address.is_v6())
8483
responders_.push_back(std::make_shared<udp_server>(
85-
info_, *ios_.back(), mcastaddr, multicast_port, multicast_ttl, listen_address));
84+
info_, *ios_.back(), address, multicast_port, multicast_ttl, listen_address));
8685
} catch (std::exception &e) {
87-
LOG_F(WARNING, "Couldn't create multicast responder for %s (%s)", mcastaddr.c_str(),
88-
e.what());
86+
LOG_F(WARNING, "Couldn't create multicast responder for %s (%s)",
87+
address.to_string().c_str(), e.what());
8988
}
9089
}
9190
}

src/udp_server.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "udp_server.h"
2+
#include "api_config.h"
23
#include "socket_utils.h"
34
#include "stream_info_impl.h"
45
#include <boost/asio/ip/address.hpp>
@@ -29,11 +30,10 @@ udp_server::udp_server(const stream_info_impl_p &info, asio::io_context &io, udp
2930
(void *)this);
3031
}
3132

32-
udp_server::udp_server(const stream_info_impl_p &info, asio::io_context &io,
33-
const std::string &address, uint16_t port, int ttl, const std::string &listen_address)
33+
udp_server::udp_server(const stream_info_impl_p &info, asio::io_context &io, ip::address addr,
34+
uint16_t port, int ttl, const std::string &listen_address)
3435
: info_(info), io_(io), socket_(std::make_shared<udp::socket>(io)),
3536
time_services_enabled_(false) {
36-
ip::address addr = ip::make_address(address);
3737
bool is_broadcast = addr == ip::address_v4::broadcast();
3838

3939
// set up the endpoint where we listen (note: this is not yet the multicast address)
@@ -60,16 +60,28 @@ udp_server::udp_server(const stream_info_impl_p &info, asio::io_context &io,
6060
// bind to the listen endpoint
6161
socket_->bind(listen_endpoint);
6262

63-
// join the multicast group, if any
63+
// join the multicast groups
6464
if (addr.is_multicast() && !is_broadcast) {
65-
if (addr.is_v4())
66-
socket_->set_option(
67-
ip::multicast::join_group(addr.to_v4(), listen_endpoint.address().to_v4()));
68-
else
69-
socket_->set_option(ip::multicast::join_group(addr));
65+
bool joined_anywhere = false;
66+
lslboost::system::error_code err;
67+
for (auto &if_ : api_config::get_instance()->multicast_interfaces) {
68+
DLOG_F(INFO, "Joining %s to %s", if_.addr.to_string().c_str(), addr.to_string().c_str());
69+
if (addr.is_v4() && if_.addr.is_v4())
70+
socket_->set_option(
71+
ip::multicast::join_group(addr.to_v4(), if_.addr.to_v4()), err);
72+
else if (addr.is_v6() && if_.addr.is_v6())
73+
socket_->set_option(
74+
ip::multicast::join_group(addr.to_v6(), if_.addr.to_v6().scope_id()), err);
75+
if (err)
76+
LOG_F(WARNING, "Could not bind multicast responder for %s to interface %s (%s)",
77+
addr.to_string().c_str(), if_.addr.to_string().c_str(), err.message().c_str());
78+
else
79+
joined_anywhere = true;
80+
}
81+
if (!joined_anywhere) throw std::runtime_error("Could not join any multicast group");
7082
}
7183
LOG_F(2, "%s: Started multicast udp server at %s port %d (addr %p)",
72-
this->info_->name().c_str(), address.c_str(), port, (void *)this);
84+
this->info_->name().c_str(), addr.to_string().c_str(), port, (void *)this);
7385
}
7486

7587
// === externally issued asynchronous commands ===

src/udp_server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class udp_server : public std::enable_shared_from_this<udp_server> {
4646
* This server will listen on a multicast address and responds only to LSL:shortinfo requests.
4747
* This is for multicast/broadcast (and optionally unicast) local service discovery.
4848
*/
49-
udp_server(const stream_info_impl_p &info, asio::io_context &io, const std::string &address,
49+
udp_server(const stream_info_impl_p &info, asio::io_context &io, asio::ip::address addr,
5050
uint16_t port, int ttl, const std::string &listen_address);
5151

5252

testing/lslcfgs/default.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
[ports]
2+
IPv6=allow
13
[lab]
24
KnownPeers=127.0.0.1

0 commit comments

Comments
 (0)