Skip to content

Commit 9710479

Browse files
committed
Validate multicast addresses, pre-filter by allowed network stacks
1 parent 37c5399 commit 9710479

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
@@ -146,32 +146,29 @@ void api_config::load_from_file(const std::string &filename) {
146146
else
147147
throw std::runtime_error("This ResolveScope setting is unsupported.");
148148

149-
multicast_addresses_.insert(
150-
multicast_addresses_.end(), machine_group.begin(), machine_group.end());
149+
std::vector<std::string> mcasttmp;
150+
151+
mcasttmp.insert(mcasttmp.end(), machine_group.begin(), machine_group.end());
151152
multicast_ttl_ = 0;
152153

153154
if (scope >= link) {
154-
multicast_addresses_.insert(
155-
multicast_addresses_.end(), link_group.begin(), link_group.end());
156-
multicast_addresses_.push_back("FF02:" + ipv6_multicast_group);
155+
mcasttmp.insert(mcasttmp.end(), link_group.begin(), link_group.end());
156+
mcasttmp.push_back("FF02:" + ipv6_multicast_group);
157157
multicast_ttl_ = 1;
158158
}
159159
if (scope >= site) {
160-
multicast_addresses_.insert(
161-
multicast_addresses_.end(), site_group.begin(), site_group.end());
162-
multicast_addresses_.push_back("FF05:" + ipv6_multicast_group);
160+
mcasttmp.insert(mcasttmp.end(), site_group.begin(), site_group.end());
161+
mcasttmp.push_back("FF05:" + ipv6_multicast_group);
163162
multicast_ttl_ = 24;
164163
}
165164
if (scope >= organization) {
166-
multicast_addresses_.insert(
167-
multicast_addresses_.end(), organization_group.begin(), organization_group.end());
168-
multicast_addresses_.push_back("FF08:" + ipv6_multicast_group);
165+
mcasttmp.insert(mcasttmp.end(), organization_group.begin(), organization_group.end());
166+
mcasttmp.push_back("FF08:" + ipv6_multicast_group);
169167
multicast_ttl_ = 32;
170168
}
171169
if (scope >= global) {
172-
multicast_addresses_.insert(
173-
multicast_addresses_.end(), global_group.begin(), global_group.end());
174-
multicast_addresses_.push_back("FF0E:" + ipv6_multicast_group);
170+
mcasttmp.insert(mcasttmp.end(), global_group.begin(), global_group.end());
171+
mcasttmp.push_back("FF0E:" + ipv6_multicast_group);
175172
multicast_ttl_ = 255;
176173
}
177174

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

185189
// The network stack requires the source interfaces for multicast packets to be
186190
// 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
@@ -21,7 +21,7 @@ resolver_impl::resolver_impl()
2121
uint16_t mcast_port = cfg_->multicast_port();
2222
for (const auto &mcast_addr : cfg_->multicast_addresses()) {
2323
try {
24-
mcast_endpoints_.emplace_back(ip::make_address(mcast_addr), (uint16_t)mcast_port);
24+
mcast_endpoints_.emplace_back(mcast_addr, mcast_port);
2525
} catch (std::exception &) {}
2626
}
2727

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<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-
ip::address address(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>
@@ -28,11 +29,10 @@ udp_server::udp_server(const stream_info_impl_p &info, asio::io_context &io, udp
2829
(void *)this);
2930
}
3031

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

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

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

7486
// === 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)